2013-12-18 36 views
5
  • 盒裝可空基本類型可投到枚舉但盒裝枚舉類型不能轉換可空類型。

同樣,盒裝可空基礎類型可以轉換爲枚舉但盒裝枚舉類型不能被轉換到空類型

  • 盒裝爲空的枚舉可以轉換到基本類型,但盒裝的基礎類型不能轉換可空枚舉。

好吧,我知道「盒裝可空字體」不是描述它的最好方式,但它是爲了這個問題。我知道這是正在裝箱的基礎值類型。

我會用示例展示它。假設我有一個enumint作爲基礎類型。

enum Sex { Male, Female } 

案例一:

int? i = 1; 
object o = i; 
Sex e = (Sex)o; //success 

//but 

Sex e = Sex.Male; 
object o = e; 
int? i = (int?)o; //invalid cast 

案例二:

Sex? e = Sex.Male; 
object o = e; 
int i = (int)o; //success 

//but 

int i = 1; 
object o = i; 
Sex? e = (Sex?)o; //invalid cast 

簡而言之,

(enum)int? -> succeeds 
(int?)enum -> the reverse fails 

(int)enum? -> succeeds 
(enum?)int -> the reverse fails 

或者甚至SIMPL呃而言,

投地不可爲空 - >成功
投可空 - >失敗

現在我知道,一旦你框的值類型,可以投退只有原來的類型。但是,由於通過C#的規則,一個盒裝int可以轉換爲enum和盒裝enum可以轉換爲int,和盒裝intint?和盒裝int?int,我一直在尋找的其他情形一致的理解,以及,即上面列出的那些。但我沒有得到邏輯。 其中之一,我覺得如果他們全都失敗了,或者他們都成功了,那開發人員就更有意義了。 二,即使成功演員看起來有點奇怪。我的意思是因爲一個值類型可以隱式地轉換爲其可空的等價物(而不是其他方式),所以無論如何都應該成功爲空,但是對於當前的實現,可以將一個可空類型轉換爲不可空如果前者具有空值,則失敗。如果整個事情都是以其他方式進行的話,理解起來會更容易。

Sex? e = null; 
object o = e; 
int i = (int)o; //succeeds, but sure to explode on cast 

//but 

int i = 1; 
object o = i; 
Sex? e = (Sex?)o; //invalid cast, even though its always a safe cast 

問題:像一個例子

  1. 那麼C#的規則讓這種情況發生?

  2. 有沒有簡單的方法可以記住這個?

+1

好問題。我認爲它實際上是CLR級別的差異,而不是C#級別。在CLR級別有*有效的各種各樣的東西,但不允許在C#級別 - 例如'int []'和'uint []'之間的轉換。 –

回答

4

我覺得這是對unboxunbox.any IL指令的精妙之處。

從ECMA 335中,部分III.4.32(unbox操作 - unbox.any是相似的)

例外:
System.InvalidCastException拋出如果OBJ不是裝箱值類型,值類型Nullable<T>obj不是盒裝的T,或者如果值的容器類型d在obj不是驗證者可分配到(III.1.8.2.3)價值類型

因此,例如,在這種情況下:

Sex e = Sex.Male; 
object o = e; 
int? i = (int?)o; 

失敗完全正確 - 因爲值類型Nullable<int>OBJ盒裝int。 「驗證者可分配給」部分不適用於Nullable<T>的情況。

我懷疑這種行爲是否在C#規範中有描述,不幸的是我不認爲從「盒裝int」到「枚舉底層類型爲int」的拆箱行爲被描述,就我而言可以看到,這是一個先決條件,然後在混合中包含可空性。

+0

規格忍者罷工! :)對不起,遲到迴應。確實很好找。雖然我不完全確定它爲何如此設計,相當混亂。 – nawfal

相關問題