2012-10-18 226 views
9

我試圖編寫一個擴展方法可爲空的枚舉。
就像這個例子:可擴展枚舉的擴展方法

// ItemType is an enum 
ItemType? item; 
... 

item.GetDescription(); 

所以我寫了這個方法,它不會編譯由於某種原因,我不明白:

public static string GetDescription(this Enum? theEnum) 
{ 
    if (theEnum == null) 
     return string.Empty; 

    return GetDescriptionAttribute(theEnum); 
} 

我越來越對Enum?以下錯誤:

唯一非空值類型可以被底層的system.nullable

爲什麼?枚舉不能有值null

更新:

如果有大量的枚舉,ItemType只是其中的一個例子。

回答

17

System.Enumclass,所以剛落?,這應該工作。

(通過「這應該工作」,我的意思是,如果你在一個空值ItemType?通過,你會在方法獲得nullEnum

public static string GetDescription(this Enum theEnum) 
{ 
    if (theEnum == null) 
     return string.Empty; 
    return GetDescriptionAttribute(theEnum); 
} 
enum Test { blah } 

Test? q = null; 
q.GetDescription(); // => theEnum parameter is null 
q = Test.blah; 
q.GetDescription(); // => theEnum parameter is Test.blah 
+0

http://msdn.microsoft.com/en-us/library/system.enum.aspx – Jacek

+0

@Jacek你是什麼意思? – Rawling

+0

@Jacek:我打算寫這篇文章,但是我測試了它,它出乎意料地工作。 – Jens

0

也許更好的是增加額外的價值,你的枚舉,並把它叫做空:)

+1

是的,我同意,一個Enum的值爲「Undefined」或「Null」,或者更有意義。或者你可以將你的枚舉包裝在一個類中,如果你真的想要一個空值,那麼將它變爲null。 –

+2

咦?完全相反的是 - 只有值類型可以與'Nullable '一起使用。 'INullable'與相關性如何? –

+0

enum null不是選項。不在asp.net-MVC – gdoron

3

你應該在你的方法簽名使用實際枚舉類型:

public static string GetDescription(this ItemType? theEnum) 

System.ValueTypeSystem.Enum如不治療值類型(僅從它們派生的類型),所以它們可以爲空(並且不要將它們指定爲可空)。試試看:

// No errors! 
ValueType v = null; 
Enum e = null; 

您也可以嘗試這樣的簽名:

public static string GetDescription<T>(this T? theEnum) where T: struct 

這也讓struct小號,雖然,這可能不是你想要的。我想我記得一些庫在編譯後(C#不允許)添加類型約束enum。只需要找到它......

編輯:發現:

http://code.google.com/p/unconstrained-melody/

+0

如果有很多枚舉,'ItemType'就是一個例子。我確信這很明顯,對不起。 – gdoron

+0

哦,你添加的第二部分回答我的問題,謝謝。但是有沒有辦法克服這種奇怪的設計? – gdoron

+0

您可以使用通用約束,但C#不允許將枚舉指定爲約束。看到我的編輯解決方案。 – Botz3000

1

你可以簡單地讓你的擴展方法通用:

public static string GetDescription<T>(this T? theEnum) where T : struct 
{ 
    if (!typeof(T).IsEnum) 
     throw new Exception("Must be an enum."); 

    if (theEnum == null) 
     return string.Empty; 

    return GetDescriptionAttribute(theEnum); 
} 

不幸的是,你不能在通用約束使用System.Enum,所以擴展方法會顯示所有空的值(因此額外的檢查)。

+0

這很好,因爲它避免了拳擊。如果你願意,你也可以說'!theEnum.HasValue'。如果有人對'System.Enum'的泛型約束感興趣,請閱讀[枚舉和委託的泛型約束](https://msmvps.com/blogs/jon_skeet/archive/2009/09/10/generic-constraints-for -enums和 - delegates.aspx)。 –