I'm using a Dictionary<int, KeyValuePair<bool, int>>
to hold data.
From time to time I need to increment the int
in the KeyValuePair
, but it won't let me, because it has no setter. Is there a way to increment it?
Code sample:
Dictionary<int, KeyValuePair<bool, int>> mDictionary =
new Dictionary<int, KeyValuePair<bool, int>>();
mDictionary[trapType].Value++;
//Error: The property KeyValuePair<TKey, Tvalue>>.Value has no setter
Is there a way to increment it?
No. KeyValuePair
is immutable - it's also a value type, so changing the value of the Value
property after creating a copy wouldn't help anyway.
You'd have to write something like this:
var existingValue = mDictionary[trapType];
var newValue = new KeyValuePair<bool, int>(existingValue.Key,
existingValue.Value + 1);
mDictionary[trapType] = newValue;
It's pretty ugly though - do you really need the value to be a KeyValuePair
?
mDictionary[trapType] = new KeyValuePair<bool, int>(mDictionary[trapType].Key, mDictionary[trapType].Value+1)
KeyValuePair
tends just to be used as an iterator value for dictionaries. You're better off defining your own type if you want it to be mutable.
another solution is to create a new dictionary and pass the new values and keys to it:
foreach (var d in existingDic)
newDic.Add(d.Key, d.Value + 1);
Conceptually, KeyValuePair<TKey,TValue>
is just a pair of variables, Key
and Value
. Had Microsoft implemented it with exposed public fields Key
and Value
, the semantics of it would have been perfect; when used as a ForEach
control variable it would have been immutable, but one could have updated the Key or Value field of an ordinary variable or array element without having to update the other.
Unfortunately, Microsoft seems to have been unwilling to have framework types expose any public fields, even for types like KeyValuePair<TKey,TValue>
or Drawing.Rectangle
whose semantics dictate that (1) the type must be a struct; (2) its entire state is visible in a fixed set of properties (there may be other computed properties beyond those which define an object's state), and (3) those properties may be assigned any combination of values suitable for their types. Consequently, Microsoft only considered the possibilities of exposing the members comprising the types' state as read-only properties, or as read-write properties. Using read-write properties would mean that code like:
for each (var item in myDictionary)
item.Value += 1;
or
...assuming MyList is a List<Drawing.Rectangle>
MyList[3].Width += 9;
would be interpreted by the existing C# compiler as either
for each (var item in myDictionary)
{ var temp = item; temp .Value += 1; }
or
...assuming MyList is a List<Drawing.Rectangle>
{ temp = MyList[3]; temp.Width += 9; }
both of yield horrible behavior which is almost certainly not what the programmer intended. The implementers of .net decided that the value of having the members of KeyValuePair<TKey,TValue>
be individually mutable did not justify the danger posed by the former, but the usefulness of modifying individual members of Rectangle
was sufficient to justify the danger posed by second. Note that neither example would have had to pose any danger had the types used exposed fields rather than properties, since writing to a field of a temporary struct has never been permissible, even when calling property setters was.
As previously mentioned, the KeyValuePair is immutable. I thought it was worth adding here a mutable implementation:
public class MutableKeyValuePair<KeyType, ValueType>
{
public KeyType Key { get; set; }
public ValueType Value { get; set; }
public MutableKeyValuePair() { }
public MutableKeyValuePair(KeyType key, ValueType val)
{
Key = key;
Value = val;
}
}
You will need to construct a new key value pair.
mDictionary[trapType] = new KeyValuePair<bool,int>(mDictionary[trapType].Key,mDictionary[trapType].Value +1);
However if you are on .NET 4, I'd suggest you use a Tuple
instead of a key value pair if what you are trying to do is simply to have an object that holds two other values. Ie if there's no key-value relationship between the two. Then code would then be:
mDictionary[trapType] = Tuple.Create(mDictionary[trapType].Item1,mDictionary[trapType].Item2 +1);
来源:https://stackoverflow.com/questions/10580029/the-property-keyvaluepairtkey-tvalue-value-has-no-setter