web-dev-qa-db-ja.com

デフォルトのコンストラクターによる配列の初期化

public class Sample
{
     static int count = 0;
     public int abc;
     public Sample()
     {
        abc = ++Sample.count;
     }
}

上記のクラスの配列を作成し、配列の各要素をデフォルトのコンストラクターを呼び出すことによって初期化して、各要素が異なるabcを持つことができるようにしたいので、これを行いました:

Sample[] samples = new Sample[100];

しかし、これは私がするべきだと私が思うことをしません。この方法では、デフォルトのコンストラクターが呼び出されないようです。配列を作成するときにデフォルトのコンストラクターを呼び出す方法は?

また、上記のステートメントの機能を教えてください。

19
Nawaz

基本的にはできません。配列を作成すると、配列には常にタイプのデフォルト値が常に入力されます-クラスの場合、これは常にnull参照です。 intの場合は0、boolの場合はfalseなどです。

(配列初期化子を使用する場合、「空の」配列が作成され、thenはもちろん、指定した値をこの配列に入力します。)

コンストラクターを呼び出すことで配列に値を設定するには、さまざまな方法があります。私はおそらく foreachループを自分で使用します。 Enumerable.Range/RepeatでLINQを使用すると、少し強制されたように感じます。

もちろん、拡張メソッドであっても、いつでもwrite独自のポピュレーションメソッドを使用できます。

public static T[] Populate<T>(this T[] array, Func<T> provider)
{
    for (int i = 0; i < array.Length; i++)
    {
        array[i] = provider();
    }
    return array;
}

それからあなたは使うことができます:

Sample[] samples = new Sample[100].Populate(() => new Sample());

このソリューションの好きなところ:

  • それはまだ単一の式であり、さまざまなシナリオで役立ちます
  • 実際に必要のない概念(単一の値の繰り返しや範囲の作成など)は導入されていません

もちろん、さらにオプションを追加することもできます。

  • Func<int, T>ではなくFunc<T>を取り、プロバイダーにインデックスを渡すオーバーロード
  • 配列を作成する非拡張メソッドandがそれを設定します
42
Jon Skeet

コードはarrayのみを作成し、その項目は作成しません。基本的に、あなたはstore instances of Sampleintoこの配列にする必要があります。

簡単に言うと、派手なLINQなどはありません。

Sample[] samples = new Sample[100];
for (int i = 0; i < samples.Length; i++) samples[i] = new Sample();

また、ソリューションはnotスレッドセーフであることにも注意してください。

8
Ondrej Tucny

これを自動的に行う方法はありません。配列の初期化は基本的に「このメモリブロックを0にワイプ」します。あなたは次のようなことをしなければなりません:

var arr = new SomeType[size];
for(int i = 0 ; i < size ; i++) arr[i] = new SomeType();
4
Marc Gravell

問題は、その配列を宣言することにより、各オブジェクトにスペースを割り当てなかったことです。 Sampleタイプの100個のオブジェクトにスペースを割り当てただけです。それぞれのコンストラクタを自分で呼び出す必要があります。

詳しく説明するには:

Food[] foods = Food[100];
for (int k = 0; k < foods.length; k++) {
   foods[k] = new Food();
}

興味深い回避策は、ファクトリ関数かもしれません。これをSampleクラスに添付することを検討してください。

public static Sample[] getInstances(int aNumber) {
    Sample[] sample = Sample[aNumber];
    for (int k = 0; k < sample.length; k++) {
       sample[k] = new Sample();
    }

    return sample;
}

少し傷を隠します-これがあなたに役立つ機能を提供します。

2
Mike

この時点でサイズ100の空の配列があり、アイテムでそれを埋める場合は、次のようにする必要があります。

for(int i=0; i<samples.Length; i++) {
   samples[i] = new Sample();
}
2
Victor

以下は、拡張メソッドを必要としない別のワンライナーです。

Sample[] array = Enumerable.Range(0, 100).Select(i => new Sample()).ToArray();

別の素晴らしいオプションは スコットの提案 から ジョンの答え です:

public static T[] Populate<T>(this T[] array) 
    where T : new()
{
    for (int i = 0; i < array.Length; i++)
        array[i] = new T();
    return array;
}

だからあなたはできる:

Sample[] array = new Sample[100].Populate();
1
Juan