为什么“int[] 是 uint[] == true"?在 C# 中 [英] Why does "int[] is uint[] == true" in C#

查看:22
本文介绍了为什么“int[] 是 uint[] == true"?在 C# 中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以澄清 C# is 关键字吗?特别是这两个问题:

Q1) 第 5 行;为什么这会返回 true?

Q2) 第 7 行;为什么没有演员表异常?

public void Test(){object intArray = new int[] { -100, -200 };if (intArray is uint[])//为什么返回true?{uint[] uintArray = (uint[])intArray;//为什么没有类转换异常?for (int x = 0; x 

MSDN 的描述没有说明情况.它指出如果满足这些条件中的任何一个,is 将返回 true.(http://msdn.microsoft.com/en-us/library/scekt9xw(VS.71).aspx>MDSN 文章)

<前>表达式不为空.表达式可以强制转换为类型.

我不相信您可以将 int[] 有效转换为 uint[].因为:

A) 此代码无法编译:

int[] signed = new int[] { -100 };uint[] 无符号 = (uint[]) 有符号;

B) 在调试器中执行强制转换会出错:

(uint[])签名无法将类型 'int[]' 转换为 'uint[]'"

果然,如果第 3 行是 int[] 而不是 object,那么它永远不会编译.这让我想到了与 Q2 相关的最后一个问题.

Q3) 为什么 C# 会在调试器和编译器中而不是在运行时引发强制转换/转换错误?

解决方案

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

您不能在 C# 中直接int[]uint[] 之间进行转换,因为语言不相信任何转换可用.但是,如果您通过 object 访问,结果取决于 CLI.来自 CLI 规范第 8.7 节(我希望 - 我引用了 不久前我与 Eric Lippert 就这个话题进行了电子邮件交流:

<块引用>

有符号和无符号整数原语类型可以相互分配;例如, int8 := uint8 是有效的.为了这目的,应该考虑 bool与 uint8 兼容,反之亦然,这使得 bool := uint8 有效,并且反之亦然.这也适用于有符号和无符号整数数组相同大小的原始类型;例如,int32[] := uint32[] 是有效的.

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

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

当 Marc 删除他的回答时,我已经链接到 Eric 的完整邮件,如张贴到 C# 新闻组.

Can somebody clarify the C# is keyword please. In particular these 2 questions:

Q1) line 5; Why does this return true?

Q2) line 7; Why no cast 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's description does not clarify the situation. It states that is will return true if either of these conditions are met. (http://msdn.microsoft.com/en-us/library/scekt9xw(VS.71).aspx>MDSN Article)

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) Doing the cast in the debugger gives an error:

(uint[])signed
"Cannot convert type 'int[]' to 'uint[]'"

Sure enough, if line 3 was int[] instead of object then it would never compile. Which brings me to a final question related to Q2.

Q3) Why does C# raise a cast/conversion error in the debugger and compiler but not at runtime?

解决方案

C# and the CLR have somewhat different conversion rules.

You can't directly cast between int[] and uint[] in C# because the language doesn't believe any conversion is available. However, if you go via object the result is up to the CLI. From the CLI spec section 8.7 (I hope - I'm quoting an email exchange I had on this topic with Eric Lippert a while ago):

Signed and unsigned integral primitive types can be assigned to each other; e.g., int8 := uint8 is valid. For this purpose, bool shall be considered compatible with uint8 and vice versa, which makes bool := uint8 valid, and vice versa. This is also true for arrays of signed and unsigned integral primitive types of the same size; e.g., int32[] := uint32[] is valid.

(I haven't checked, but I assume that this sort of reference type conversion being valid is what makes is return true as well.)

It's somewhat unfortunate that there are disconnects between the language and the underlying execution engine, but it's pretty much unavoidable in the long run, I suspect. There are a few other cases like this, but the good news is that they rarely seem to cause significant harm.

EDIT: As Marc deleted his answer, I've linked to the full mail from Eric, as posted to the C# newsgroup.

这篇关于为什么“int[] 是 uint[] == true"?在 C# 中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆