Método para agregar nuevo o actualizar elemento existente en el diccionario

235

En algunos códigos heredados, he visto el siguiente método de extensión para facilitar la adición de un nuevo elemento clave-valor o la actualización del valor, si la clave ya existe.

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 algún escenario posible?

Además, creo que esto solía ser la diferencia entre HashTable y Dictionary. HashTable permite actualizar un elemento, o agregar un nuevo elemento mediante el 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 lanzar una excepción si el usuario envía el mismo valor clave nuevamente, el método solo debe actualizar la entrada con el nuevo valor y hacer una nueva entrada si se ha enviado un nuevo par clave-valor al método .

Manish Basantani
fuente

Respuestas:

243

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

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


Con respecto a Dictionary<>vs Hashtable.: Cuando inicia Reflector, ve que los establecedores del indexador de ambas clases llaman this.Insert(key, value, add: false);y el addparámetro es responsable de lanzar una excepción, al insertar una clave duplicada. Entonces el comportamiento es el mismo para ambas clases.

ulrichb
fuente
44

No hay problema. Incluso eliminaría el CreateNewOrUpdateExistingde la fuente y lo usaría map[key] = valuedirectamente en su código, porque esto es mucho más legible, porque los desarrolladores generalmente sabrían lo que map[key] = valuesignifica.

Steven
fuente
22

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 existe el espacio de nombres System.Collections.Concurrentque incluye colecciones que son seguras para subprocesos.

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

Si se encuentra en un escenario de alto rendimiento y no maneja múltiples subprocesos, las respuestas ya dadas map[key] = valueson más rápidas.

En la mayoría de los escenarios, este beneficio de rendimiento es insignificante. Si es así, aconsejaría usar ConcurrentDictionary porque:

  1. Está en el marco: está más probado y usted no es quien debe mantener el código
  2. Es escalable: si cambia a subprocesos múltiples, su código ya está preparado para ello
Luis Filipe
fuente
7

Funcionalmente, son equivalentes.

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

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

En la mayoría de los casos, el código parece funcionar bien en un contexto de subprocesos múltiples. No obstante, es no seguro para subprocesos sin sincronización adicional.

ya23
fuente