2012-05-14 15 views
6

Estoy usando Dictionary<int, KeyValuePair<bool, int>> para almacenar datos.
De vez en cuando necesito incrementar el "int" en el KeyValuePair, pero no me deja, porque no tiene setter.
¿Hay alguna manera de incrementarlo?La propiedad KeyValuePair <TKey, Tvalue> .Value no tiene setter

ejemplo de código:

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

en el método:

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

Respuesta

21

¿Hay una manera de incrementarlo?

KeyValuePair es inmutable - también es un tipo de valor, por lo que cambiar el valor de la propiedad Value después de crear una copia no ayudaría de todos modos.

Habría que escribir algo como esto:

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

Es bastante feo, aunque - no se realmente necesita el valor de ser un KeyValuePair?

+3

Sugeriría 'Tuple'. La forma más corta de crear uno sería 'Tuple.Create (existingValue.Key, existingValue.Value + 1)'. Aunque crear una clase, si es lógico, sería mejor evitar '' new() ''innecesarios. – SimpleVar

+0

@YoryeNathan: Sí, eso probablemente sería apropiado, o un tipo separado con nombres de propiedades que reflejen los verdaderos significados de 'bool' y' int'. (Veo que también ha editado su comentario :) –

+0

Sí, aunque puedo imaginar casos en los que esto se usaría en un pequeño alcance para algún algoritmo peculiar, en cuyo caso yo personalmente preferiría un tipo anónimo. – SimpleVar

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

KeyValuePair tiende a ser utilizado como un valor iterador para los diccionarios. Será mejor que defina su propio tipo si desea que sea mutable.

0

You Will nuevo para construir un nuevo par de valores clave

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

Sin embargo, si usted está en .NET 4. Yo sugeriría que utilice triples en lugar del valor de par de claves si lo que está intentando es simplemente tener un objeto que tenga otros dos valores. Es decir, si no hay una relación clave-valor entre los dos. A continuación, el código sería entonces:

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

otra solución es crear un nuevo diccionario y aprobar los nuevos valores y claves a la misma:

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

Conceptualmente, KeyValuePair<TKey,TValue> es sólo un par de variables, Key y Value. Si Microsoft lo hubiera implementado con los campos públicos expuestos Key y Value, la semántica habría sido perfecta; cuando se usa como variable de control ForEach, hubiera sido inmutable, pero se podría haber actualizado el campo Clave o Valor de una variable ordinaria o elemento de matriz sin tener que actualizar el otro.

Desafortunadamente, Microsoft parece haber sido reacio a tener tipos de marcos exponer cualquier campo público, incluso para tipos como KeyValuePair<TKey,TValue> o Drawing.Rectangle cuya semántica dicta que (1) el tipo debe ser una estructura; (2) su estado completo es visible en un conjunto fijo de propiedades (puede haber otras propiedades calculadas más allá de las que definen el estado de un objeto), y (3) a esas propiedades se les puede asignar cualquier combinación de valores adecuados para sus tipos. En consecuencia, Microsoft solo consideró las posibilidades de exponer los miembros que comprenden el estado de los tipos como propiedades de solo lectura o como propiedades de lectura/escritura.Utilización de las propiedades de lectura-escritura significaría que un código como:

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

o

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

sería interpretado por el compilador de C# existente como sea

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

tanto de rendimiento horrible comportamiento vior, que es casi seguro que no es lo que pretendía el programador. Los implementadores de .net decidieron que el valor de tener los miembros de KeyValuePair<TKey,TValue> individualmente mutable no justificaba el peligro planteado por el primero, pero la utilidad de modificar miembros individuales de Rectangle fue suficiente para justificar el peligro planteado por el segundo. Tenga en cuenta que ninguno de los ejemplos habría tenido que representar ningún peligro si los tipos hubieran usado campos expuestos en lugar de propiedades, ya que nunca se ha permitido escribir en un campo de una estructura temporal, incluso cuando se llamaba a los instaladores de propiedades.

0

Como se mencionó anteriormente, KeyValuePair es inmutable. Pensé que valía la pena agregar aquí una implementación mutable:

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