2012-05-14 9 views
6

sto usando Dictionary<int, KeyValuePair<bool, int>> per contenere i dati.
Di tanto in tanto ho bisogno di incrementare "int" in KeyValuePair, ma non me lo consente, perché non ha setter.
C'è un modo per incrementarlo?La proprietà KeyValuePair <TKey, TValue> .Value non ha setter

codice di esempio:

Dictionary<int, KeyValuePair<bool, int>> mDictionary = 
    new Dictionary<int, KeyValuePair<bool, int>>(); 

nel metodo:

mDictionary[trapType].Value++; 
//Error: The property KeyValuePair<TKey, Tvalue>>.Value has no setter 

risposta

21

C'è un modo per incrementarlo?

No. KeyValuePair è immutabile - è anche un tipo di valore, in modo da cambiare il valore della proprietà Valuedopo la creazione di una copia non aiuterebbe comunque.

Dovresti scrivere qualcosa del genere:

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

E 'abbastanza brutto anche se - si fa davvero necessario il valore di essere un KeyValuePair?

+3

Suggerirei 'Tupla'. Il modo più semplice per crearne uno sarebbe 'Tuple.Create (existingValue.Key, existingValue.Value + 1)'. Sebbene la creazione di una classe, se logica, sarebbe meglio evitare inutili 'new()' s. – SimpleVar

+0

@YoryeNathan: Sì, sarebbe probabilmente appropriato - o un tipo separato con nomi di proprietà che riflettono i significati reali di 'bool' e' int'. (Vedo che hai modificato il tuo commento anche per questo :) –

+0

Sì, anche se posso immaginare casi in cui questo sarebbe usato in un piccolo ambito per qualche algoritmo bizzarro, nel qual caso preferirei personalmente un tipo anonimo. – SimpleVar

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

KeyValuePair tende solo da utilizzare come valore iteratore dizionari. Stai meglio definendo il tuo tipo se vuoi che sia mutabile.

0

You Will nuovo per costruire una nuova coppia di valori chiave

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

Tuttavia, se siete su .NET 4. Vorrei suggerire di usare triple invece di coppia chiave-valore se ciò che si sta cercando di è semplicemente avere un oggetto che contiene altri due valori. Cioè se non c'è nessuna relazione-valore tra i due. Poi il codice sarebbe allora:

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

un'altra soluzione è quella di creare un nuovo dizionario e trasmettere i nuovi valori e le chiavi ad esso:

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

Concettualmente, KeyValuePair<TKey,TValue> è solo una coppia di variabili, Key e Value. Aveva Microsoft ha implementato con campi esposti pubblici Key e Value, la semantica di essa sarebbe stato perfetto; se usato come variabile di controllo ForEach sarebbe stato immutabile, ma si sarebbe potuto aggiornare il campo Chiave o Valore di una variabile ordinaria o di un elemento dell'array senza dover aggiornare l'altro.

Purtroppo, Microsoft sembra essere stato disposto a avere tipi quadro espongono i campi pubblici, anche per tipi come KeyValuePair<TKey,TValue> o Drawing.Rectangle cui semantica impongono che (1) il tipo deve essere una struttura; (2) il suo intero stato è visibile in un insieme fisso di proprietà (potrebbero esserci altre proprietà calcolate oltre a quelle che definiscono lo stato di un oggetto), e (3) a quelle proprietà può essere assegnata qualsiasi combinazione di valori adatta per i loro tipi. Di conseguenza, Microsoft ha considerato solo le possibilità di esporre i membri che comprendono lo stato dei tipi come proprietà di sola lettura o come proprietà di lettura-scrittura.Utilizzando le proprietà di lettura-scrittura vorrebbe dire che il codice come:

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

o

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

verrebbe interpretato dal compilatore C# esistenti sia come

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

o

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

entrambi comportano un comportamento orribile vior che non è quasi certamente ciò che il programmatore intendeva. Gli esecutori di .net hanno deciso che il valore di avere i membri di KeyValuePair<TKey,TValue> individualmente mutabili non giustificava il pericolo posto dal primo, ma l'utilità di modificare i singoli membri di Rectangle era sufficiente a giustificare il pericolo posto dal secondo. Nota che nessuno dei due esempi avrebbe dovuto rappresentare un pericolo se i tipi usassero campi esposti piuttosto che proprietà, dal momento che scrivere in un campo di una struttura temporanea non è mai stato permesso, anche quando si chiamavano i setter delle proprietà.

0

Come accennato in precedenza, KeyValuePair è immutabile. Ho pensato che valesse la pena aggiungere qui un'implementazione mutabile:

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