array creation expressions and long dimension lengths

孤人 提交于 2019-12-10 19:41:15

问题


I was just reading the C# specification and the part on array creation expressions. In the specification it says:

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

[snip]

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.

Excited, I thought hmm I don't think I've seen that yet, let's try a long dimension length:

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

Visual Studio says while pointing to the first line:

Unhandled Exception: System.OverflowException: Arithmetic operation resulted in an overflow.

Note this is NOT an "OutOfMemoryException". If I change my array creation expression and make it a little smaller:

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

This time I get an "OutOfMemoryException". I know about the whole "no object can be larger than 2GB" restriction from the CLR. My question is why am I getting a very different exception (OverflowException vs OutOfMemoryException) when the length is no longer convertible to Int32?


回答1:


The compiler can infer a larger integral type based upon the inputs to the dimensions calculation, but that does not mean the length of the array can exceed the limit. The compiler is basically converting the value to a native integer in a checked context, using an op code that will throw the overflow. This is to prevent the value from wrapping or otherwise allowing a negative number as the dimension.

As an example, note the array declaration here:

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

And the resultant 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

Pay particular attention to the third line. That op code is the instruction to produce the conversion and throws the exception upon failure.



来源:https://stackoverflow.com/questions/14889333/array-creation-expressions-and-long-dimension-lengths

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!