Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “为什么?”;int[]是uint[]==true";在C中#_C#_Arrays_Casting_Unsigned - Fatal编程技术网

C# “为什么?”;int[]是uint[]==true";在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

谁能澄清一下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 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[]

您可以将int强制转换为uint,但它的行为非常奇怪。VisualStudio无法识别其中任何一项,即使是手表,当附加调试器时,它只会显示一个问号“?”

您可能想看一看,快进大约10分钟,听Anders解释共变体阵列的实现。我认为这是根本的根本问题
Animal[] tigers = new Tiger[10];
tigers[3] = new Elephant(); // ArrayTypeMismatchException