有人可以澄清一下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#新闻组。

09-30 12:55
查看更多