C# リスト オブジェクトの値が上書きされます: 参照セマンティックの問題
リストに新しい値を追加すると、リスト内のすべての項目が以前の値を上書きするのはなぜですか?この不可解な動作は、C# の基礎となるデータ構造と参照セマンティクスに起因します。
クラスと構造体のセマンティクスを理解する
C# では、クラスは参照型です。つまり、クラス型の変数はメモリ内の実際のオブジェクトの場所への参照を保存します。一方、構造体は値型であり、変数は実際のデータを直接保持します。
提供されたコード スニペット内:
<code class="language-csharp">List<Tag> tags = new List<Tag>(); Tag _tag = new Tag(); string[] tagList = new[] { "Foo", "Bar" }; foreach (string t in tagList) { _tag.tagName = t; // 设置所有属性 tags.Add(_tag); // 覆盖之前的数值 }</code>
_tag
は参照型であるため、tags.Add(_tag)
操作は同じオブジェクトへの参照をリストに追加します。その結果、リスト内のすべての要素は実際には同じインスタンスを指します。 _tag
を使用してインスタンスを変更すると、リスト内のすべての項目が変更されます。
新しいインスタンスを作成して問題を解決します
上書きを防ぐには、ループの反復ごとに新しい Tag
インスタンスを作成する必要があります。
<code class="language-csharp">foreach (string t in tagList) { Tag _tag = new Tag(); // 为每次迭代创建一个新实例 _tag.tagName = t; tags.Add(_tag); }</code>
各反復では新しい Tag
インスタンスが作成され、リスト内の各オブジェクトが独自の一意の値を持つようになります。
補足: 構造体とクラス
クラスの代わりに構造体を使用すると、構造体は値型であるため、上書きの問題がなくなります。構造体が新しい変数に割り当てられると、独自の値のセットを含む完全に新しいインスタンスが作成されます。したがって、tags.Add(_tag)
はコピー操作を実行しますが、以前に追加された項目には影響しません。
要約すると、C# のオブジェクトのリストにおける上書きの問題を回避するには、参照セマンティクスとクラスと構造体の違いを理解することが重要です。
以上がC# でリスト項目が互いに上書きされるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。