c# - 数组创建表达式和长维度长度

标签 c# overflowexception

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

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

[剪断]

The dimension length expressions of the expression-list are evaluated in order, from left to right. Following evaluation of each expression, an implicit conversion (§6.1) to one of the following types is performed: int, uint, long, ulong. The first type in this list for which an implicit conversion exists is chosen. If evaluation of an expression or the subsequent implicit conversion causes an exception, then no further expressions are evaluated and no further steps are executed.

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

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)?

最佳答案

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

例如,请注意此处的数组声明:

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是产生转换并在失败时抛出异常的指令。

关于c# - 数组创建表达式和长维度长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14889333/

相关文章:

c# - MVC 4 回发空 View 模型

c# - 为什么将 int.MinValue 除以 -1 在未经检查的上下文中抛出 OverflowException?

.net - 为什么十进制->字节转换会发生溢出异常,而uint->字节却不会?

c# - 如何使用 C# 读取 .sil(SmartInspect 文件)日志文件

c# - 找到超速的时期?

c# - 将未命名的json数组反序列化为c#中的对象

c# - Decimal.Round() 如何抛出 OverflowException

c# - 应用程序关闭时将信息存储到文件的正确方法

c# - 减去两个 System.Runtime.InteropServices.ComTypes.FILETIME 对象的最安全方法是什么

c# - 复制到数据表时,值对于 Int16 来说太大或太小