プログラミングとかブログ

Unity/C#/SRPGStudio/RPGツクールMVの情報とかその他気になったことを調べて書きます。

【C#】Enumerable.Repeatの誤解

以下のクラスがあります。

class Test
{
    public int a = 0;
    public Test(int i) { a = i; }
}

このクラスの配列を作ろうと以下のコードを書きました。

Test[] Arr = Enumerable.Repeat(new Test(1), 2).ToArray();

これは以下のコードと等価だ―そんなふうに考えていた時期が俺にもありました

Test[] Arr2 = { new Test(1), new Test(1) };

ところが以下のように要素1のint変数に代入すると

Arr[1].a = 114514;

なぜかArr[0].aも同じ値になってしまいます。
f:id:shirakamisauto:20160304142600p:plain
Arr2の場合はちゃんとArr2[1]だけ代入されています。
f:id:shirakamisauto:20160304142611p:plain

どうやらRepeatでは各要素に新規インスタンスを突っ込んでいるのではなく、指定値へのポインタを突っ込んでいるようです。
おそらく以下のような動作になっていると思われます。

var t1 = new Test(1);
Arr[0] = t1;
Arr[1] = t1;

ReferenceEqualsメソッドで確かめます。
f:id:shirakamisauto:20160304142617p:plain
Repeatのほうは各要素が同じ参照を示しており、通常の配列初期化ではそれぞれ別の参照を示していることがわかります。

結論
Enumerable.Repeatの値に参照型を使うときは注意。
値型なら問題ないです。