有人可以澄清一下C#is
关键字。特别是以下两个问题:
Q1)第5行;为什么返回真?
Q2)第7行;为什么没有强制转换异常(exception)?
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文章)expression is not null. expression can be cast to type.
I don't believe that you can do a valid cast of int[] into uint[]. Because:
A) This code does not compile:
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[]
之间进行转换,因为该语言认为无法进行任何转换。但是,如果您通过object
进行操作,则结果取决于CLI。从CLI规范第8.7节开始(我希望-不久前我引用了email exchange I had on this topic with Eric Lippert):
(我没有检查过,但是我认为这种引用类型转换有效也是使is
返回true的原因。)
不幸的是,语言与底层执行引擎之间存在脱节,但是从长远来看,这是不可避免的。还有其他一些类似的情况,但是好消息是它们似乎很少造成重大伤害。
编辑:当马克删除他的答案时,我已经链接到Eric的完整邮件,该邮件已发布到C#新闻组。