51

C#で新しい配列を割り当てるときはいつでも

new T[length]

配列エントリはデフォルトのTに設定されます。これは、が参照型nullである場合、またはが値型である場合はT、のデフォルトコンストラクタの結果である場合です。TT

私の場合Int32、値-1で配列を初期化したいです。

var myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { myArray[i] = -1; }

したがって、メモリが配列用に予約された後、CLRは新しく割り当てられたメモリをループし、すべてのエントリをdefault(int)= 0に設定します。その後、私のコードはすべてのエントリを-1に設定します。

これにより、初期化が冗長になります。JITはこれを検出し、0への初期化を無視しますか?そうでない場合、カスタム値でメモリの一部を直接初期化する方法はありますか?

C#配列の初期化を参照すると、デフォルト値以外の場合、新しい配列が割り当てられ、後で値がコピーされるため、usingEnumerable.Repeat(value, length).ToArray()はオプションではありません。Enumerable.ToArray

4

6 に答える 6

35

ダンの答えに似ていますが、コレクションを使用する必要はありません:

int[] myArray = Enumerable.Repeat(-1, 100).ToArray();
于 2009-09-29T17:33:34.950 に答える
33

冗長ではありません。

初期化ループ中に例外がスローされたとします。CLRが最初にメモリをクリアしていない場合、初期化されていない元のメモリを「見る」ことができる可能性があります。これは、特にセキュリティの観点から、非常に悪い考えです。そのため、CLRは、新しく割り当てられたメモリが0ビットパターンにワイプされることを保証します。

ちなみに、同じ議論がオブジェクトのフィールドにも当てはまります。

どちらの場合も、CLRは、初期化を完了する前に配列を他の場所に表示しないことを確認できると思いますが、非常に単純な「メモリのこの領域を消去する」ことを避けるための複雑な確認です。

于 2009-03-15T23:42:30.380 に答える
10

多少有害であると考えられる配列を受け入れる場合、次のように書くと、質問は意味がありません。

var myArray = new List<int>(Enumerable.Repeat(-1, 100));
于 2009-03-16T00:08:43.577 に答える
3

JITがこのシナリオのデフォルトセットを最適化することは非常に疑わしいです。その理由は、これが観察可能な違いになるからです。次のわずかに変更されたシナリオを考えてみましょう。

obj.myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { obj.myArray[i] = -1; }

ループがスローされる可能性は完全にあります。少なくとも、JITがそうでないことを証明することはおそらく不可能です。スローされ、CLRがデフォルトでメモリを初期化しない場合、objへの参照がまだある場合は、結果を観察できます。

于 2009-03-15T23:44:13.840 に答える
2

Array.Fill配列に初期値を入力するための非常に簡潔な方法として使用することをお勧めします。

bool[] isPrime = new bool[MaxNum];
Array.Fill(isPrime, true);

isPrimeこれにより、配列内のすべての値が に初期化されtrueます。

于 2019-01-08T13:03:49.453 に答える