В KeyValuePair собственность.Значение не имеет задатчика

Я использую Dictionary<int, KeyValuePair<bool, int>> для хранения данных.

время от времени мне нужно прирастить int на KeyValuePair, но он не позволит мне, потому что это не сеттер. Есть ли способ увеличить его?

код:

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 ответов


есть ли способ увеличить его?

нет. KeyValuePair является неизменяемым-это также тип значения, поэтому изменение значения Value свойства после создания копии все равно не поможет.

вы должны написать что-то вроде этого:

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

это довольно уродливо, хотя-вы действительно нужно значение, чтобы быть KeyValuePair?


mDictionary[trapType] = new KeyValuePair<bool, int>(mDictionary[trapType].Key, mDictionary[trapType].Value+1)

KeyValuePair имеет тенденцию просто использоваться в качестве значения итератора для словарей. Вам лучше определить свой собственный тип, если вы хотите быть уникальным.


другое решение-создать новый словарь и передать ему новые значения и ключи:

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

концептуально, KeyValuePair<TKey,TValue> - это всего лишь пары переменных, Key и Value. Если бы Microsoft реализовала его с открытыми открытыми полями Key и Value, семантика этого была бы идеальной; при использовании в качестве ForEach переменная управления это было бы неизменяемо, но можно было бы обновить поле ключа или значения обычной переменной или элемента массива без необходимости обновлять другой.

к сожалению, Microsoft, похоже, не желала иметь типы рамок предоставляют любые открытые поля, даже для таких типов, как KeyValuePair<TKey,TValue> или Drawing.Rectangle семантика которого диктует ,что (1) тип должен быть структурой; (2) все его состояние видно в фиксированном наборе свойств (могут быть другие вычисляемые свойства, кроме тех, которые определяют состояние объекта), и (3) этим свойствам может быть присвоена любая комбинация значений, подходящих для их типов. Следовательно, Microsoft рассматривала только возможности раскрытия членов, содержащих состояние типов, как свойства только для чтения или для чтения и записи свойства. Использование свойств чтения-записи будет означать, что код, например:

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

или

...assuming MyList is a List<Drawing.Rectangle>
MyList[3].Width += 9;

будет интерпретироваться существующим компилятором C# как либо

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

или

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

оба выхода ужасное поведение, которое почти наверняка не то, что задумывал программист. Разработчики .net решили, что значение наличия членов KeyValuePair<TKey,TValue> быть индивидуально изменяемым не оправдать опасность, которую представляют первые, но полезность модификации отдельных членов Rectangle было достаточно, чтобы оправдать опасность, исходящую от второго. Обратите внимание, что ни один пример не должен был представлять никакой опасности, если бы типы использовали открытые поля, а не свойства, поскольку запись в поле временной структуры никогда не была допустимой, даже когда вызывались задатчики свойств.


Как уже упоминалось ранее, KeyValuePair является неизменяемым. Я подумал, что стоит добавить сюда изменяемую реализацию:

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

вам нужно будет построить новую пару ключ-значение.

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

однако, если вы находитесь на .NET 4, я бы предложил вам использовать Tuple вместо пары ключ-значение, если то, что вы пытаетесь сделать, это просто объект, который имеет два других значения. Т. е. если между ними нет отношения ключ-значение. Тогда код будет такой:

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