4

コレクションに保存する必要のある構造体があります。構造体には、ディクショナリを返すプロパティがあります。

public struct Item
{
    private IDictionary<string, string> values;
    public IDictionary<string, string> Values
    {
        get
        {
            return this.values ?? (this.values = new Dictionary<string, string>());
        }
    }
}

public class ItemCollection : Collection<Item> {}

テストしたところ、アイテムをコレクションに追加してからディクショナリにアクセスしようとすると、structvaluesプロパティが更新されないことがわかりました。

 var collection = new ItemCollection { new Item() }; // pre-loaded with an item
 collection[0].Values.Add("myKey", "myValue");
 Trace.WriteLine(collection[0].Values["myKey"]); // KeyNotFoundException here

ただし、最初にアイテムをロードしてからコレクションに追加すると、値フィールドは維持されます。

 var collection = new ItemCollection();
 var item = new Item();
 item.Values.Add("myKey", "myValue");
 collection.Add(item);
 Trace.WriteLine(collection[0].Values["myKey"]); // ok

このタイプでは構造体が間違ったオプションであるとすでに判断しており、クラスを使用しても問題は発生しませんが、2つのメソッドの違いに興味があります。誰かが何が起こっているのか説明できますか?

4

3 に答える 3

2

代わりに構造体をクラスに変更します。

public class Item {}

今、私は内部に精通していませんが、構造体は値型であり、クラスは参照型であり、最初のコード例を実行したときに例外が発生する理由を説明するロジックがそこにあると信じています.

誰かが介入して、より徹底的な回答を提供してくれることを願っていますが、今のところ、構造体をクラスに変更してください。

于 2012-09-19T09:31:12.260 に答える
1

前述のとおり、 に変更struct Itemclass Itemます。を使用するstructと、式は でcollection[0]作成されたオブジェクトへの参照を返すのではなく、new ItemCollection { new Item() }そのコピーを作成してユーザーに渡します。

于 2012-09-19T09:40:06.540 に答える
1

「アイテム」は価値のあるアイテムです。つまり、コレクションにアクセスすると、コピーが作成されます。すべての操作はそのコピーに対して行われます

 collection[0].Values.Add("myKey", "myValue");

ここで最初の項目のコピーが作成され、Value get アクセサーが新しいインスタンスを作成し、それがコピーに格納されてから、項目が追加されます。その後、コピーは破棄されます。

回避策は、構造体の作成時に直接値ディクショナリを作成することです

public struct Item
{
    private IDictionary<string, string> values = new Dictionary<string, string>();
    public IDictionary<string, string> Values
    {
        get
        {
            return this.values;
        }
    }
}

コレクションにアクセスすると、コピーが作成されます。ただし、このコピーには、元のものと同じ値辞書への参照が含まれています。そのため、元の辞書が変更されます

于 2012-09-19T09:36:25.510 に答える