2012-06-08 35 views
6

は、次のことを考えてみましょう:大きな配列の割り当て。 OutOfMemoryException VS OverflowExceptionが

long size = int.MaxValue; 
long[] huge = new long[size];  // throws OutOfMemoryException 
long[] huge = new long[size + 1]; // throws OverflowException 

私は最初の例外を説明し、単一のオブジェクトのサイズに2GBの制限がある知っているが、なぜ私は要素の数いったん別の例外を得るのですか32ビットを上回る?

(これは重要な場合は64ビットコンピュータを使用しています)

編集:私はまた、問題なくlongを受け付けるインデクサを定義して使用することができる:

internal sealed class MyClass 
{ 
    public object this[long x] 
    { 
     get 
     { 
     Console.WriteLine("{0}", x); 
     return null; 
     } 
    } 
} 

... 

long size = int.MaxValue; 
MyClass asdf = new MyClass(); 
object o = asdf[size * 50]; // outputs 107374182350 
+0

代わりに、必要に応じて多くのメモリしか使用しない汎用リスト 'List 'を使用してください。 –

答えて

2

:一般的に

  • インデクサは、パラメータのいずれかのタイプを使用することができます。
  • はビルトイン配列インデクサー...
  • しかしビルトイン配列インデクサーの基礎となる実装を任意の整数型を受け入れることができ<= Int32.MaxValueある値を必要とし、超過する値のためにオーバーフロー例外がスローされますInt32.MaxValue

後者の点は、(Int32より大きいタイプを受け入れていますが、実際にそれらの余分のビットのいずれかを使用して起こる場合に例外をスロー)奇妙な矛盾のいくつかの種類のように感じているが、それは明らかにの副作用であります実際には、このうちのいくつかは、Int32.MaxValue以上の要素を持つことができる配列の将来の実装のために半分実装されているという事実です。

8

C#の配列はSystem.Int32によって索引付けされています。 size + 1Int32.MaxValueを超えているため、整数オーバーフローが発生します。

実際にlongをインデックスとして使用する場合は、オーバーロードの代わりにArray.CreateInstanceを使用します。私が収集したものを、次のようなものがここで起こっているからそう

+0

したがって、値が32ビットより大きくない場合にのみ、インデックスまたはサイズ指定子として 'long'変数を使用することができます。それは奇妙に思われる。コンパイラは 'Int32'を必要としませんか? 32ビットがインデックスの制限である場合、なぜ 'long'sをインデックスとして使うのですか? –

+1

配列添字(indexers: '[index]')を使うと、 'int'だけ使うことができます。 'long'を使いたい場合は、' GetValue'メソッドと 'SetValue'メソッドを使用する必要があります。 –

+3

'Array.CreateInstance'は問題を解決しないことを指摘する価値があります。まだ大きすぎる配列を作成することはできません。関連する質問はこちら[こちら](http://stackoverflow.com/questions/10945404/why-is-long-being-allowed-as-array-length-in-c/10945507#10945507)、.NET 4.5より大きい配列は、64ビットシステムでサポートされています。すべての整数型は、コンパイル時に配列の初期化子として使用できます。 –

関連する問題