2009-07-24 11 views
98

Devo aggiungere coppie di chiavi/oggetti a un dizionario, ma ovviamente devo prima controllare se la chiave esiste già altrimenti ottengo un errore "già esistente nel dizionario". Il codice qui sotto risolve questo problema ma è goffo.C'è un modo più elegante di aggiungere un elemento ad un dizionario <> in modo sicuro?

Che cosa è un modo più elegante di fare questo senza fare un metodo di stringa di helper come questo?

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

risposta

187

Basta usare l'indicizzatore - sarà sovrascritto se è già lì, ma non è così ha essere lì prima:

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

Fondamentalmente utilizzare Add se l'esistenza della chiave indica un bug (quindi lo vuoi gettare) e l'indicizzatore altrimenti. (. E 'un po' come la differenza tra casting e utilizzando as per le conversioni di riferimento)

Se stai usando C# 3 e si dispone di una serie distinta di chiavi, è possibile rendere questo ancora più ordinato:

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

Tuttavia, ciò non funzionerà nel tuo caso, poiché gli inizializzatori di raccolta utilizzano sempre Add che verrà aggiunto alla seconda voce Customers.

+2

eccellente, non si rese conto semplice assegnazione ha curato l'add/problema di sovrascrittura, bello. –

36

Cosa c'è di sbagliato con ...

dict[key] = view; 

Sarà aggiungere automaticamente la chiave se è inesistente.

18

semplicemente

dict[key] = view; 

Dalla documentazione MSDN di Dictionary.Item

Il valore associato alla chiave specificata . Se la chiave specificata è non trovata, un'operazione get lancia una chiave KeyNotFoundException e un'operazione impostata crea un nuovo elemento con la chiave specificata .

mia enfasi

8

Come al solito John Skeet ottiene in là con velocità di illuminazione con la risposta giusta, ma è interessante notare che si poteva anche aver scritto il tuo SafeAdd come un metodo di estensione su IDictionary.

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

Sebbene l'utilizzo l'indicizzatore è chiaramente la risposta giusta per il vostro problema specifico, un'altra risposta più generale al problema di aggiungere ulteriori funzionalità ad un tipo esistente sarebbe di definire un metodo di estensione.

Obviousy questo non è un utile esempio particolarmente, ma qualcosa da tenere a mente per la prossima volta a trovare una reale necessità:

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

Direi che è applicabile solo a C# 3.0 e versioni successive. –

Problemi correlati