2012-10-04 71 views
8

我剛從一個讓我瘋狂的同事得到了這個測驗。對於這個代碼片段:可空類型GetType()拋出異常

var x = new Int32?(); 
string text = x.ToString(); // No exception 
Console.WriteLine(text); 
Type type = x.GetType(); // Bang! 

爲什麼在第一部分的ToString()的工作沒有出現任何的異常,然後調用的GetType()拋出一個NullReferenceException?

回答

17

ToStringoverridden in Nullable<T>,所以沒有拳擊參與打電話。

GetType()不是一個虛擬的方法,所以不是(也不能)重寫,所以在調用之前將值裝箱...並且裝填可空值類型的空值給出空引用。

其原因拳擊是在C#4規範的7.5.5節:

M如果處於引用類型聲明的實例函數成員:

  • ..
  • 如果E的類型是值型,則執行裝箱轉換(4.3.1)以將E轉換爲型和E在以下步驟中被認爲是object類型。在這種情況下,M只能是System.Object

注意的成員,如果你有:

var x = new Int32?(10); 

你再次結束與類型是一樣的typeof(int),由於拳擊。無法創建值foo,因此foo.GetType()使用正常的GetType()方法返回可爲空的值類型。 (您可以創建過程中的一個GetType()方法,但是這是一個枝節問題:)

(使用「砰!」暗示說測驗可能是我的。道歉筆者驅動你瘋了,如果是這樣的case)。

+0

好吧..但是,爲什麼然後用最後一行替換:var boxed =(Int32)x;拋出InvalidOperationException而不是?是不是拳擊,應該拋出同樣的例外? – kabaros

+0

@kabaros:不,根本不是拳擊 - 「Int32?」和「Int32」都不是引用類型。這是C#4規範第6.2.3節中描述的明確轉換。 –

+1

哦,當然,這是非常有道理的。非常感謝。順便說一句好書,所以你原諒我們瘋狂:) – kabaros

相關問題