属性KeyValuePair .Value没有setter

我正在使用Dictionary<int, KeyValuePair>来保存数据。

我不时需要在KeyValuePair增加int ,但它不会让我,因为它没有setter。 有没有办法增加它?

代码示例:

 Dictionary<int, KeyValuePair> mDictionary = new Dictionary<int, KeyValuePair>(); mDictionary[trapType].Value++; //Error: The property KeyValuePair>.Value has no setter 

有没有办法增加它?

KeyValuePair是不可变的 – 它也是一个值类型,因此在创建副本后更改Value属性的Value无论如何都无济于事。

你必须写这样的东西:

 var existingValue = mDictionary[trapType]; var newValue = new KeyValuePair(existingValue.Key, existingValue.Value + 1); mDictionary[trapType] = newValue; 

虽然这很丑陋 – 你真的需要价值成为KeyValuePair吗?

 mDictionary[trapType] = new KeyValuePair(mDictionary[trapType].Key, mDictionary[trapType].Value+1) 

KeyValuePair往往只是用作字典的迭代器值。 如果你希望它是可变的,你最好定义自己的类型。

另一个解决方案是创建一个新的字典并将新的值和键传递给它:

 foreach (var d in existingDic) newDic.Add(d.Key, d.Value + 1); 

从概念上讲, KeyValuePair只是一对变量, KeyValue 。 如果微软用暴露的公共字段KeyValue实现它,它的语义就会很完美; 当用作ForEach控件变量时,它将是不可变的,但是可以更新普通变量或数组元素的Key或Value字段,而不必更新另一个。

不幸的是,微软似乎不愿意让框架类型暴露任何公共字段,即使是像KeyValuePairDrawing.Rectangle这样的类型,其语义规定(1)类型必须是结构; (2)其整个状态在一组固定的属性中可见(除了定义对象状态的属性之外,可能还有其他计算属性),以及(3)可以为这些属性分配适合其类型的任何值组合。 因此,Microsoft仅考虑了将包含类型状态的成员公开为只读属性或读写属性的可能性。 使用读写属性意味着代码如下:

 for each (var item in myDictionary) item.Value += 1; 

要么

 ...assuming MyList is a List MyList[3].Width += 9; 

将被现有的C#编译器解释为

 for each (var item in myDictionary) { var temp = item; temp .Value += 1; } 

要么

 ...assuming MyList is a List { temp = MyList[3]; temp.Width += 9; } 

产生可怕的行为几乎肯定不是程序员的意图。 .net的实施者认为让KeyValuePair的成员具有个体可变性的价值并不能certificate前者造成的危险,但修改Rectangle个体成员的有用性足以certificate由此构成的危险。第二。 请注意,如果类型使用公开的字段而不是属性,则两个示例都不必构成任何危险,因为即使在调用属性setter时,也不允许写入临时结构的字段。

如前所述,KeyValuePair是不可变的。 我认为值得在这里添加一个可变的实现:

 public class MutableKeyValuePair { public KeyType Key { get; set; } public ValueType Value { get; set; } public MutableKeyValuePair() { } public MutableKeyValuePair(KeyType key, ValueType val) { Key = key; Value = val; } } 

您需要构造一个新的键值对。

 mDictionary[trapType] = new KeyValuePair(mDictionary[trapType].Key,mDictionary[trapType].Value +1); 

但是,如果您使用的是.NET 4,我建议您使用Tuple而不是键值对,如果您要做的只是拥有一个包含其他两个值的对象。 即如果两者之间没有键值关系。 然后代码将是:

 mDictionary[trapType] = Tuple.Create(mDictionary[trapType].Item1,mDictionary[trapType].Item2 +1);