2009-09-24 60 views
2

我修改了擴展方法Thorarin了響應this問題上的一個int而不是字符串工作蒙上錯誤到'TEnum'。「在最後一行。詮釋在通用擴展

如果該行被更改爲此:

return (TEnum)(object)intEnumValue; 

它編譯和作品。

爲什麼int需要先轉換爲object?

回答

5

無法將int直接投射到未知類型,因此編譯器將不允許(TEnum)intEnumValue。這兩個石膏你現在正在做實際上是微妙的不同:(object)int,而(TEnum)鑄盒裝intTEnum,這是靜態允許的,因爲它是靜態類型object的表達可能實際上是運行時類型TEnum的。

可能還有一些微妙之處:通常,盒裝intcan only be unboxed to int。我想我已經解釋了編譯器允許轉換的原因,但不是爲什麼它也被運行時所允許。也許轉換爲TEnum只允許在運行時,因爲TEnum碰巧是一個枚舉有int作爲其基本類型?我想我記得讀過CLR中的枚舉實際上只是它們基類型的實例。

編輯:我證實了我的懷疑:

public static void Main() 
{ 
    int value = 1; 

    IntEnum i = ToEnum<IntEnum>(value); // Valid cast, runs fine. 
    ByteEnum b = ToEnum<ByteEnum>(value); // Invalid cast exception! 
} 

public enum ByteEnum : byte { } 

public enum IntEnum : int { } 

public static TEnum ToEnum<TEnum>(int value) 
{ 
    return (TEnum)(object)value; 
} 

所以我們可以有把握地說,(TEnum)在盒裝int是唯一有效的,如果TEnum實際上是在幕後的int

+0

是否有更直接的方法從Enum的基礎類型轉到Enum? – 2009-09-24 14:50:46

+1

Enum.ToObject(typeof(TEnum),intEnumValue)as TEnum – plinth 2009-09-24 14:53:41

0

當您使用(TEnum)intEnumValue進行強制轉換時,編譯器不知道要使用哪種類型的TEnum類。由於int只能隱式轉換爲某些類,編譯器會失敗。鑄造對象是可以接受的,然後TEnum是一個對象,所以鑄造也是可能的。

0

TEnum是一種任意類型。你可以投一個int到矩形?到DateTime?編譯器不知道,不幸的是規範說你不能在它上面添加一個約束。

2

Eric Lippert有關於此類問題的博客文章here。基本上,有幾種不同類型的'cast',從int到TEnum可能是其中的一種。所以,唯一安全的方法是將int整理到一個對象中,然後在運行時嘗試將其轉換爲TEnum。你不能直接從int到TEnum,因爲需要做什麼取決於TEnum是什麼,並且只在運行時才知道。