C# “为什么?”;int[]是uint[]==true";在C中#
谁能澄清一下C#C# “为什么?”;int[]是uint[]==true";在C中#,c#,arrays,casting,unsigned,C#,Arrays,Casting,Unsigned,谁能澄清一下C#是关键字吗。特别是这两个问题: 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
是
关键字吗。特别是这两个问题:
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]);
}
}
}
我不相信您可以将int[]有效地转换为uint[]。因为:
A) 此代码不编译:
int[] signed = new int[] { -100 };
uint[] unsigned = (uint[])signed;
B) 在调试器中执行强制转换时出现错误:
(uint[])signed
"Cannot convert type 'int[]' to 'uint[]'"
果不其然,如果第3行是int[]而不是object,那么它将永远不会编译。这就引出了与Q2相关的最后一个问题
问题3)为什么C#在调试器和编译器中而不是在运行时引发强制转换/转换错误?建议:
将intArray声明为“int[]intArray”而不是“object intArray”将允许编译器拾取无效的C#cast。除非你必须使用object,否则我会采用这种方法
关于第二季度、第三季度:
在运行时,您是否尝试过将强制转换包装到块中
来自MSDN的这篇文章:
默认情况下,一个表达式
仅包含常量值导致
如果表达式
生成的值不在
目标类型的范围。如果
表达式包含一个或多个
非常量值,编译器执行
没有检测到溢出
默认情况下,这些参数是非常量的
表达式不被检查
在运行时溢出,并且
不要引发溢出异常。这个
前面的示例显示
-2147483639作为两个正整数之和
溢出检查可以通过以下方式启用:
编译器选项,环境
配置,或使用选中的
关键词
正如它所说的,您可以通过编译器设置或环境配置更全局地强制执行溢出检查
在您的情况下,这可能是可取的,因为它将导致抛出运行时错误,从而确保可能的无效无符号数到有符号数溢出不会悄无声息地发生
[Update]在测试了这段代码之后,我发现使用object类型的声明而不是int[]似乎绕过了标准的C#casting sytax,无论是否启用了checked
正如JS所说,当您使用object时,您受到CLI规则的约束,这些规则显然允许这种情况发生
关于Q1:
这与上述情况有关。简而言之,由于涉及强制转换,因此它不会引发异常(基于当前溢出设置)。这是否是一个好主意是另一个问题
:
如果提供的表达式为非null,则“is”表达式的计算结果为true,并且
可以将提供的对象强制转换为提供的类型,而不会导致异常发生
扔
我猜测与.NET 1的向后兼容性:我仍然对细节有点模糊,但我认为所有数组的CLR类型都只是System.Array,带有额外的类型属性来查找元素类型。”is“可能只是在CLR v1中没有考虑到这一点,现在必须保持这一点 它在
(uint[])(new int[]{}
情况下不起作用可能是因为C#编译器(不是CLR运行时)能够执行更严格的类型检查
此外,阵列通常是类型不安全的:
Animal[] tigers = new Tiger[10];
tigers[3] = new Elephant(); // ArrayTypeMismatchException
C#和CLR有一些不同的转换规则
在C语言中,不能直接在int[]
和uint[]
之间进行转换,因为该语言不相信有任何转换可用。但是,如果通过object
进行操作,则结果取决于CLI。从CLI规范第8.7节(我希望-我刚才引用):
有符号和无符号整数原语
类型可以相互分配;
e、 例如,int8:=uint8是有效的。为此
目的,应考虑bool
与uint8兼容,反之亦然,
这使得bool:=uint8
有效,并且
反之亦然。这也适用于中国
有符号和无符号整数数组
相同大小的原始类型;
e、 例如,int32[]:=uint32[]
有效
(我没有检查,但我假设这种引用类型转换是有效的,这使得is
也返回true。)
有点不幸的是,语言和底层执行引擎之间存在脱节,但我怀疑,从长远来看,这几乎是不可避免的。还有一些类似的案例,但好消息是它们似乎很少造成重大伤害
编辑:当马克删除了他的答案时,我已经链接到了埃里克的完整邮件,该邮件已发布到C#新闻组。好的
我想试试看
首先,文档说,“检查对象是否与给定类型兼容”。它还说,如果左侧的类型是“可转换”(您可以毫无例外地转换)到右侧的类型,并且表达式的计算结果为非null,“is”关键字的计算结果为true
寻找乔恩·斯基特的另一个答案。他说得比我更有说服力。他是对的,如果转换可用,它将接受您的语法,您可以随后编写自己的语法,但在这种情况下,这似乎有些过分
参考资料:这很有趣。我在ECMA-335标准中找到了这个。4.3课堂。请注意:
- 数组继承自System.Array
- 如果Foo可以转换为Bar,那么Foo[]可以转换为Bar[]
- 出于上述注释2的目的,枚举被视为其基础类型:因此,如果E1和E2共享基础类型,则E1[]可以转换为E2[]
Animal[] tigers = new Tiger[10];
tigers[3] = new Elephant(); // ArrayTypeMismatchException