2013-05-20 131 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的实际装箱值,以及您调用的方法(可能通过委派给其他某个函数)执行的转换。