有人可以澄清一下C#is关键字。特别是以下两个问题:
is
Q1)第5行;为什么返回真?
Q2)第7行;为什么没有强制转换例外?
public void Test() { object intArray = new int[] { -100, -200 }; if (intArray is uint[]) //why does this return true? { uint[] uintArray = (uint[])intArray; //why no class cast exception? for (int x = 0; x < uintArray.Length; x++) { Console.Out.WriteLine(uintArray[x]); } } }
MSDN的描述并未阐明这种情况。它声明is如果满足这些条件之一,则将返回true。(http://msdn.microsoft.com/zh- cn/library/scekt9xw(VS.71).aspx>MDSN文章)
表达式不为null。 表达式可以强制转换为类型。
我不认为您可以将int []转换为uint []。因为:
A)此代码无法编译:
int[] signed = new int[] { -100 }; uint[] unsigned = (uint[])signed;
B)在调试器中进行强制转换会产生错误:
(uint[])signed "Cannot convert type 'int[]' to 'uint[]'"
果然,如果第3行是int []而不是object,那么它将永远不会编译。这给我带来了与第二季度有关的最后一个问题。
Q3)为什么C#在调试器和编译器中会引发转换/转换错误,而在运行时却不会?
C#和CLR的转换规则有些不同。
您不能 直接 在C#int[]和uint[]C#之间进行转换,因为该 语言 认为无法进行任何转换。但是,如果您查看object结果,则取决于CLI。在CLI规范的第8.7节中(希望-我引用了一段时间前与Eric Lippert进行的有关此主题的电子邮件交流):
int[]
uint[]
object
有符号和无符号整数基元类型可以相互分配。例如,int8:= uint8有效。为此,布尔应被视为与之兼容,uint8反之亦然,这是bool := uint8有效的,反之亦然。对于相同大小的有符号和无符号整数基元类型的数组也是如此。例如,int32[] := uint32[]有效。
uint8
bool := uint8
int32[] := uint32[]
(我没有检查过,但我认为这种引用类型转换有效也是使isreturn为true的原因。)
不幸的是,语言和底层执行引擎之间存在脱节,但从长远来看,这是不可避免的。还有其他一些类似的情况,但是好消息是它们似乎很少造成重大伤害。
编辑:当马克删除他的答案时,我已经链接到Eric的完整邮件,该邮件已发布到C#新闻组。