2013-05-20 160 views
4

方法Array.SetValue(Object value,int index)允許使用常用索引器語法通常允許的涉及值/數組類型對的賦值,並且在嘗試使用通用索引器語法時會引發異常結合通常不被允許的類型。例如,考慮下面的局部變量聲明:將字節值賦給char數組

int[] twoints = new int[2] { 5, 6 }; 

下面四行不拋出任何運行時或編譯時異常:

twoints[1] = (sbyte)7; 
twoints.SetValue((sbyte)7, 1); 
twoints[1] = (char)7; 
twoints.SetValue((char)7, 1); 

在另一方面,這四個的行會拋出一個異常,無論是在運行時或在設計時:

twoints[1] = 4.5; 
twoints.SetValue(4.5, 1); 
twoints[1] = 4L; 
twoints.SetValue(4L, 1); 

然而,當我一個字節的值賦給一個字符數組,我得到了奇怪的結果。索引器的語法在編譯時被拒絕,並且的SetValue的API調用成功,在運行時:

char[] twochars = new char[2] { 'A', 'B' }; 
twochars[1] = (byte)70;     // Not OK, refused by the compiler 
twochars.SetValue((byte)70, 1);   // OK, no exception at run-time 

這是爲什麼呢操作允許?

回答

2

這是因爲Array.SetValue()遵循CLR規則,但分配遵循類型安全的C#規則。

大多數情況下,小整數類型的局部變量和臨時對象實際上在CIL中使用native int。 「類型」是由C#編譯器創建和實施的錯覺。

在賦值中,IL操作數堆棧上有一個native int,而C#編譯器根據類型System.Byte和隱式轉換整型類型的C#規則執行類型檢查。 CLR非常樂意將值寫入數組......錯誤消息由C#編譯器添加。它可能應該是一個警告,但C#語言設計者選擇指定它是一個錯誤。

Array.SetValue中,您有一個類型爲System.Byte的實際裝箱值,以及您調用的方法(可能通過委派給其他某個函數)執行的轉換。