C# で List<T>
に項目を追加すると、予期しない結果が生じる場合があります。すべての項目が最後に追加された項目と同一になります。この記事では、その理由と修正方法について説明します。
簡略化したシナリオを見てみましょう:
<code class="language-csharp">List<Tag> tags = new List<Tag>(); Tag _tag = new Tag(); // Problem: Single instance reused string[] tagList = new[] { "Foo", "Bar" }; foreach (string t in tagList) { _tag.tagName = t; tags.Add(_tag); }</code>
この問題は、ループ内で同じ _tag
インスタンスを再利用することに起因します。各反復で同じオブジェクトが変更され、その結果、すべてのリスト エントリが最終値を保持します。
解決策: 各アイテムの新しいインスタンス
正しいアプローチは、ループの反復ごとに新しい _tag
オブジェクトを作成することです。
<code class="language-csharp">foreach (string t in tagList) { Tag _tag = new Tag(); // New instance each time _tag.tagName = t; tags.Add(_tag); }</code>
これにより、リストの各要素が個別のオブジェクトとなり、一意の値が保持されます。
ボーナス: 構造体の動作
興味深いことに、Tag
がクラスではなく構造体であった場合、元のコードは正しく動作します。 この違いは、クラスと構造体がメモリ割り当てを処理する方法に起因します。
クラスは参照型です。クラスを値で渡すと、オブジェクト自体ではなく参照のみがコピーされます。 メソッド内のパラメータを変更すると、元のオブジェクトが変更されます。 ただし、構造体は値型です。構造体を値で渡すとコピーが作成されます。 したがって、_tag
(構造体) をリストに追加するとコピーが追加され、上書きが防止されます。
以上がリストに項目を追加すると上書きされるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。