我有一个需要存储在集合中的结构。 struct有一个返回Dictionary的属性。
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> {}
测试时我发现如果我将项目添加到集合中然后尝试访问字典,那么结构值属性永远不会更新。
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
我已经确定结构是这种类型的错误选项,并且在使用类时问题不会发生,但我很好奇这两种方法之间有什么不同。任何人都可以解释发生了什么吗?
答案 0 :(得分:2)
将结构更改为类:
public class Item {}
现在我不熟悉内部,但结构是值类型而类是引用类型,我相信有逻辑可以解释为什么在运行第一个代码示例时会出现异常
我希望有人可以介入给你一个更全面的答案,但就目前而言,只需将结构更改为一个类。
答案 1 :(得分:1)
“项目”是一个有价值的项目。这意味着,如果您访问该集合,则会创建一个副本。所有操作都在该副本上完成
collection[0].Values.Add("myKey", "myValue");
这里是第一个复制项目,然后Value get访问器创建一个新实例,该实例存储在副本中,然后添加该项目。然后副本被销毁。
解决方法是直接在创建struct
时创建Values字典public struct Item
{
private IDictionary<string, string> values = new Dictionary<string, string>();
public IDictionary<string, string> Values
{
get
{
return this.values;
}
}
}
如果您访问该集合,则会制作副本。但是这个副本包含与原始字典相同的值字典的引用。所以修改了原始字典
答案 2 :(得分:1)
如前所述,将struct Item
更改为class Item
。当您使用struct
时,表达式collection[0]
不会返回对new ItemCollection { new Item() }
中创建的对象的引用,而是创建它的副本并将其提供给您。