2010-11-22 12 views
155

En algún código heredado, he visto el siguiente método de extensión para facilitar la adición de un nuevo elemento clave-valor o actualizar el valor, si la clave ya existe.Método para agregar nuevo o actualizar elemento existente en el diccionario

Método-1 (código heredado).

public static void CreateNewOrUpdateExisting<TKey, TValue>(
    this IDictionary<TKey, TValue> map, TKey key, TValue value) 
{    
    if (map.ContainsKey(key)) 
    { 
     map[key] = value; 
    } 
    else 
    { 
     map.Add(key, value); 
    } 
} 

sin embargo, he comprobado que map[key]=value hace exactamente el mismo trabajo. Es decir, este método podría reemplazarse con el Método-2 a continuación.

Método-2.

public static void CreateNewOrUpdateExisting<TKey, TValue>(
    this IDictionary<TKey, TValue> map, TKey key, TValue value) 
{ 
    map[key] = value; 
} 

Ahora, mi pregunta es ... ¿Podría haber algún problema si reemplazo el Método-1 por el Método-2? ¿Se romperá en cualquier escenario posible?

Además, creo que esta solía ser la diferencia entre HashTable y Dictionary. HashTable permite actualizar un elemento o agregar un nuevo elemento mediante el uso de un indexador, mientras que el diccionario no lo hace. ¿Se ha eliminado esta diferencia en las versiones C#> 3.0?

El objetivo de este método no es arrojar una excepción si el usuario envía la misma clave-valor nuevamente, el método solo debe actualizar la entrada con el nuevo valor y hacer una nueva entrada si se ha creado un nuevo par clave-valor enviar al método.

Respuesta

153

¿Podría haber algún problema si reemplazo el Método-1 por el Método-2?

No, solo use map[key] = value. Las dos opciones son equivalentes.


En cuanto Dictionary<> vs Hashtable: Al iniciar el reflector, se ve que los emisores de indexador de ambas clases llaman this.Insert(key, value, /* add */ false); y el parámetro add es responsable de lanzar una excepción, al insertar una clave duplicada. Entonces el comportamiento es el mismo para ambas clases.

29

No hay problema. Incluso eliminaría el CreateNewOrUpdateExisting de la fuente y usaría map[key] = value directamente en su código, porque esto es mucho más legible, porque los desarrolladores normalmente sabrían qué significa map[key] = value.

5

Funcionalmente, son equivalentes.

En cuanto al rendimiento map[key] = value sería más rápido, ya que solo está realizando una búsqueda única en lugar de dos.

En cuanto al estilo, más corto es el mejor :)

El código será en la mayoría de los casos parecen funcionar bien en un contexto multi-hilo. Sin embargo, es no thread-safe sin sincronización adicional.

13

Pregunta anterior, pero creo que debería agregar lo siguiente, aún más porque .net 4.0 ya se había lanzado en el momento en que se escribió la pregunta.

Comenzando con .net 4.0 hay el espacio de nombres System.Collections.Concurrent que incluye colecciones que son seguras para subprocesos.

La colección System.Collections.Concurrent.ConcurrentDictionary<> hace exactamente lo que quiere. Tiene el método AddOrUpdate() con la ventaja adicional de ser seguro para subprocesos.

Si se encuentra en un escenario de alto rendimiento y no maneja varios hilos, las respuestas ya dadas de map[key] = value son más rápidas.

En la mayoría de los escenarios, este beneficio de rendimiento es insignificante. Si es así, te aconsejo utilizar el ConcurrentDictionary porque:

  1. Es en el marco - es más probado y no eres el que tiene que mantener el código
  2. Es escalable: si se cambia para multithreading su código ya está preparado para él
Cuestiones relacionadas