一尘不染

为什么在C#中“ int []是uint [] == true”

c#

有人可以澄清一下C#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#在调试器和编译器中会引发转换/转换错误,而在运行时却不会?


阅读 343

收藏
2020-05-19

共1个答案

一尘不染

C#和CLR的转换规则有些不同。

您不能 直接 在C#int[]uint[]C#之间进行转换,因为该 语言
认为无法进行任何转换。但是,如果您查看object结果,则取决于CLI。在CLI规范的第8.7节中(希望-我引用了一段时间前与Eric
Lippert进行的有关此主题
电子邮件交流):

有符号和无符号整数基元类型可以相互分配。例如,int8:= uint8有效。为此,布尔应被视为与之兼容,uint8反之亦然,这是bool := uint8有效的,反之亦然。对于相同大小的有符号和无符号整数基元类型的数组也是如此。例如,int32[] := uint32[]有效。

(我没有检查过,但我认为这种引用类型转换有效也是使isreturn为true的原因。)

不幸的是,语言和底层执行引擎之间存在脱节,但从长远来看,这是不可避免的。还有其他一些类似的情况,但是好消息是它们似乎很少造成重大伤害。

编辑:当马克删除他的答案时,我已经链接到Eric的完整邮件,该邮件已发布到C#新闻组。

2020-05-19