2009-07-24 10 views
98

Necesito agregar pares clave/objeto a un diccionario, pero por supuesto necesito verificar primero si la clave ya existe, de lo contrario obtengo una "clave que ya existe en el diccionario" error. El código a continuación resuelve esto, pero es torpe.¿Existe alguna forma más elegante de agregar un elemento a un Diccionario <> de forma segura?

¿Cuál es una forma más elegante de hacer esto sin hacer un método de ayudante de cuerda como este?

using System; 
using System.Collections.Generic; 

namespace TestDictStringObject 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Dictionary<string, object> currentViews = new Dictionary<string, object>(); 

      StringHelpers.SafeDictionaryAdd(currentViews, "Customers", "view1"); 
      StringHelpers.SafeDictionaryAdd(currentViews, "Customers", "view2"); 
      StringHelpers.SafeDictionaryAdd(currentViews, "Employees", "view1"); 
      StringHelpers.SafeDictionaryAdd(currentViews, "Reports", "view1"); 

      foreach (KeyValuePair<string, object> pair in currentViews) 
      { 
       Console.WriteLine("{0} {1}", pair.Key, pair.Value); 
      } 
      Console.ReadLine(); 
     } 
    } 

    public static class StringHelpers 
    { 
     public static void SafeDictionaryAdd(Dictionary<string, object> dict, string key, object view) 
     { 
      if (!dict.ContainsKey(key)) 
      { 
       dict.Add(key, view); 
      } 
      else 
      { 
       dict[key] = view; 
      } 
     } 
    } 
} 

Respuesta

187

sólo tiene que utilizar el indexador - sobrescribirá si ya está ahí, pero no es así tener estar allí en primer lugar:

Dictionary<string, object> currentViews = new Dictionary<string, object>(); 
currentViews["Customers"] = "view1"; 
currentViews["Customers"] = "view2"; 
currentViews["Employees"] = "view1"; 
currentViews["Reports"] = "view1"; 

usar Básicamente Add si la existencia de la llave indica un error (por lo que desea arrojar) y el indexador de lo contrario. (. Es un poco como la diferencia entre la fundición y el uso de as para las conversiones de referencia)

Si estás usando C# 3 y tiene un conjunto distinto de teclas, se puede hacer esto aún más ordenado:

var currentViews = new Dictionary<string, object>() 
{ 
    { "Customers", "view2" }, 
    { "Employees", "view1" }, 
    { "Reports", "view1" }, 
}; 

Eso no funcionará en su caso, ya que los inicializadores de colección siempre usan Add que lanzarán en la segunda entrada Customers.

+2

Excelente, no se dio cuenta simple asignación se hizo cargo de la adición/sobrescribir problema, agradable. –

36

¿Qué hay de malo en ...

dict[key] = view; 

Se va a añadir automáticamente la clave si es que no existe.

18

simplemente

dict[key] = view; 

De la documentación de MSDN de Dictionary.Item

El valor asociado a la clave especificada . Si la clave especificada es no encontrada, una operación de obtención arroja una KeyNotFoundException, y una operación de establece crea un nuevo elemento con la clave especificada.

Mi énfasis

8

Como de costumbre John Skeet consigue allí con la velocidad de la iluminación con la respuesta correcta, pero, curiosamente, también se podría haber escrito su SafeAdd como un método de extensión en IDictionary.

public static void SafeAdd(this IDictionary<K, T>. dict, K key, T value)... 
4

Aunque el uso del indexador es claramente la respuesta correcta para su problema específico, otra respuesta más general al problema de añadir funcionalidad adicional a un tipo existente sería definir un método de extensión.

Obviousy esto no es un ejemplo útil particularmente, pero es algo a tener en cuenta para la próxima vez que encuentre una necesidad real:

public static class DictionaryExtensions 
{ 
    public static void SafeAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict, 
              TKey key, TValue value) 
    { 
     dict[key] = value; 
    } 
} 
+1

Menciono que esto solo es aplicable a C# 3.0 y superiores. –

Cuestiones relacionadas