2012-08-31 24 views

回答

26

不,這不拆箱 - 它只是檢查是否類型是正確的。不要忘記,確實有一個對象涉及到一個類型。無論該值是否爲裝箱值類型值,檢查該類型基本上都是相同的操作。 (對於值類型或任何密封類型,可能有一些優化是可行的,因爲沒有要考慮的繼承,但基本上它仍在檢查對象頭的「類型」部分。)

檢查的一種方法是編譯該代碼,並期待在IL使用ILASM:

// object o = 10 
IL_0000: ldc.i4.s 10 
IL_0002: box  [mscorlib]System.Int32 
IL_0007: stloc.0 

// int i = (int) o; 
IL_0008: ldloc.0 
IL_0009: unbox.any [mscorlib]System.Int32 
IL_000e: stloc.1 

// bool isInt = o is int 
IL_000f: ldloc.0 
IL_0010: isinst  [mscorlib]System.Int32 

所以它使用isinst - 沒有拆箱是必要的。

+2

因此,CLR可以檢查類型而不拆箱? –

+3

@ViacheslavSmityukh:是的。不要忘記,確實有一個對象涉及到一個類型。無論該值是否爲裝箱值類型值,檢查該類型基本上都是相同的操作。 –

+2

@JonSkeet您可以將該評論編輯爲答案,我認爲解釋*爲什麼*,而不僅僅是通過IL進行證明尤其有價值。 – Servy

5

不僅不需要拆箱,在邏輯上它不能。

拆箱可能成功或失敗,具體取決於對象是否確實包含我們將嘗試拆箱的類型的值。

因此,拆箱需要檢查對象是否屬於該特定類型。

因此,如果測試類型所需拆箱,然後因爲拆箱,需要測試的類型,我們就不能拆箱,直到我們會先拆箱...

因此測試類型不能要求拆箱。

0

從C#7開始,is關鍵字在與模式匹配的模式匹配中獲得了新的用例。在這種情況下,拆箱確實發生e.g:

object o = 10; 
if (o is int i) { 
    // i is the unboxed value. 
} 

顯然,這是一個不同的情況下,以原來的職位的其中值純粹是正在測試中,使用is爲一種模式時一樣,你實際上是分配價值。因此在這種情況下需要取消裝箱。

要清楚 - 關於原始o is int的情況沒有任何變化 - 根據舊的答案,不會發生拆箱。 is關鍵字剛剛獲得新角色。

相關問題