【问题标题】:array creation expressions and long dimension lengths数组创建表达式和长维度长度
【发布时间】:2013-02-15 06:23:22
【问题描述】:

我只是在阅读 C# 规范和数组创建表达式的部分。在规范中它说:

array-creation-expression:
new   non-array-type   [   expression-list ]   rank-specifiersopt   array-initializeropt
new   array-type   array-initializer
new   rank-specifier   array-initializer

[剪辑]

计算表达式列表的维度长度表达式 按顺序,从左到右。在评估每个表达式之后, 到以下类型之一的隐式转换(第 6.1 节)是 执行:int、uint、long、ulong。此列表中的第一个类型 选择存在隐式转换。如果评估一个 表达式或随后的隐式转换导致异常, 然后不再评估其他表达式,也不再执行其他步骤 执行。

兴奋,我想嗯我还没有看到,让我们试试长尺寸长度:

bool[] bb = new bool[2L + Int32.MaxValue];
bb[int.MaxValue + 1L] = true;

Visual Studio 指着第一行说:

未处理的异常:System.OverflowException:算术运算导致溢出。

请注意,这不是“OutOfMemoryException”。如果我更改我的数组创建表达式并使其更小:

bool[] bb = new bool[Int32.MaxValue];

这一次我得到一个“OutOfMemoryException”。我知道 CLR 的整个“没有对象可以大于 2GB”的限制。我的问题是,当长度不再可转换为 Int32 时,为什么我会得到一个非常不同的异常(OverflowException 与 OutOfMemoryException)?

【问题讨论】:

    标签: c# overflowexception


    【解决方案1】:

    编译器可以根据维度计算的输入推断出更大的整数类型,但这并不意味着数组的长度可以超过限制。编译器基本上是在检查的上下文中将值转换为本机整数,使用会引发溢出的操作码。这是为了防止值换行或以其他方式允许负数作为维度。

    例如,注意这里的数组声明:

    var array = new int[2L + int.MaxValue];
    

    以及由此产生的 IL

    IL_0001:  ldc.i4      01 00 00 80 
    IL_0006:  conv.u8     
    IL_0007:  conv.ovf.i 
    IL_0008:  newarr      System.Int32
    IL_000D:  stloc.0     // array
    

    特别注意第三行。 op code 是产生转换并在失败时引发异常的指令。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多