The property KeyValuePair.Value has no sette

2019-04-07 04:35发布

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

7条回答
Anthone
2楼-- · 2019-04-07 04:41

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?

查看更多
Viruses.
3楼-- · 2019-04-07 04:48

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);
查看更多
Summer. ? 凉城
4楼-- · 2019-04-07 04:53

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.

查看更多
太酷不给撩
5楼-- · 2019-04-07 04:56

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.

查看更多
做个烂人
6楼-- · 2019-04-07 05:00

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;
        }
    }
查看更多
我命由我不由天
7楼-- · 2019-04-07 05:01
mDictionary[trapType] = new KeyValuePair<bool, int>(mDictionary[trapType].Key, mDictionary[trapType].Value+1)
查看更多
登录 后发表回答