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> {}

在测试时,我发现如果我将项目添加到集合中然后尝试访问字典,则 structs values 属性永远不会更新。

 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

我已经确定结构是这种类型的错误选项,并且在使用类时不会出现问题,但我很好奇这两种方法之间有什么不同。谁能解释发生了什么?

4

3 回答 3

2

将您的结构更改为一个类:

public class Item {}

现在我对内部结构不太熟悉,但结构是值类型,类是引用类型,我相信其中有逻辑可以解释为什么在运行第一个代码示例时会出现异常。

我希望有人可以介入给你一个更彻底的答案,但现在,只需将结构更改为一个类。

于 2012-09-19T09:31:12.260 回答
1

“项目”是价值项目。这意味着,如果您访问该集合,则会制作一个副本。所有操作都在该副本上完成

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

这里对第一项进行了复制,然后 Value get 访问器创建了一个新实例,该实例存储在副本中,然后添加了该项。然后副本被销毁。

一种解决方法是在创建结构时直接创建 Values 字典

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 回答
1

如前所述,更改struct Itemclass Item. 当您使用struct时,表达式collection[0]不会返回对在中创建的对象的引用,new ItemCollection { new Item() }而是创建它的副本并将其提供给您。

于 2012-09-19T09:40:06.540 回答