2010-01-26 11 views

Odpowiedz

138

Zakładając chcesz uzyskać wartość wtedy, gdy klucz robi istnieje, użyj Dictionary<TKey, TValue>.TryGetValue:

int value; 
if (dictionary.TryGetValue(key, out value)) 
{ 
    // Key was in dictionary; "value" contains corresponding value 
} 
else 
{ 
    // Key wasn't in dictionary; "value" is now 0 
} 

(Korzystanie ContainsKey a następnie bibliotekarz sprawia, że ​​dwa razy spojrzeć klawisz w górę, co jest dość bezcelowe.)

Należy pamiętać, że nawet jeśli były użyciu typów referencyjnych, sprawdzanie wartości null nie będzie działać - bibliotekarz dla Dictionary<,> rzuci wyjątek, jeśli poprosisz brakującego klucza, zamiast wracać puste. (Jest to duża różnica między Dictionary<,> i Hashtable.)

+0

@JonSkeet To nie TryGetValue również wykonuje podwójne wyszukiwanie ([jak podano w treści tego pytania] (http://stackoverflow.com/questions/1413304/net-adding-dictionary-item-check-if-it-exists- lub-allow-exception))? – nawfal

+2

@nawfal: Nie widzę żadnego wskazania, że ​​to pytanie w ogóle stwierdza. Mówi, że robi więcej pracy niż 'ContainsKey', co jest prawdą, ponieważ musi również wyodrębnić wartość. Nie robi jednak dwóch poszukiwań. –

+0

Naiwnie oczekiwałem wartości null, ale dla Dictionary zwraca to odpowiednik "0" w wyliczeniu. – Jess

7

Jeśli jesteś po prostu sprawdzenie przed próbuje dodać nową wartość, należy użyć metody ContainsKey:

if (!openWith.ContainsKey("ht")) 
{ 
    openWith.Add("ht", "hypertrm.exe"); 
} 

Jeśli sprawdzenie, czy wartość istnieje, użyj metody TryGetValue jak opisano w odpowiedzi Jon Skeet za .

+5

TryGet lepiej –

+2

Bo jesteś rozwiązywania kluczową odnośnika poprzez hashtable dwukrotnie jeśli natychmiast uzyskać po Zawiera. Wintellect PowerCollections ma również metody "GetValueElseAdd", które dajesz wartość (lub 'Func '), aby również zapisać rozdzielczość na Insert, jeśli chcesz dodać, jeśli jej tam nie ma. Sądzę, że powodem, dla którego nie wprowadzono go do bibliotek .NET jest to, że ścieżka Add jest rzadsza, jeśli używasz go w stylu pamięci podręcznej] –

+0

@rub: Myślę, że to zależy od celu kodu. Jeśli chcesz użyć wartości, zgadzam się, że 'TryGetValue' byłaby lepsza, ale jeśli chcesz sprawdzić, czy słownik zawiera klucz w celu uniknięcia duplikowania dodatków, powiedziałbym, że' ContainsKey' jest równie dobry (jeśli nie lepszy). –

2

Powinieneś sprawdzić Dictionary.ContainsKey (klawisz int) przed próbą wyciągnięcia wartości.

Dictionary<int, int> myDictionary = new Dictionary<int, int>(); 
myDictionary.Add(2,4); 
myDictionary.Add(3,5); 

int keyToFind = 7; 
if(myDictionary.ContainsKey(keyToFind)) 
{ 
    myValueLookup = myDictionay[keyToFind]; 
    // do work... 
} 
else 
{ 
    // the key doesn't exist. 
} 
+2

Dlaczego chcesz zrobić to dwa razy? –

+1

@Jon, ponieważ zwykle czyta się lepiej – mookid8000

+2

@mookid: Nie według mnie. Chodzi o to, aby spróbować wyszukać klucz i podjąć jeden kurs akcji, jeśli zostanie znaleziony, a inny sposób działania w przeciwnym razie, prawda? –

0

Należy prawdopodobnie użyć:

if(myDictionary.ContainsKey(someInt)) 
{ 
    // do something 
} 

Powodem, dlaczego nie można sprawdzić null jest, że kluczem tutaj jest typ wartości.

+1

Typ wartości jest nieco nieistotny, ponieważ sprawdzanie wartości zerowej nie przyniosłoby pożądanego efektu. –

+0

@Johannes, rozwiązanie Jona jest oczywiście o wiele lepsze, ale osoba pytająca oświadczyła, że ​​sprawdził, czy klucz istnieje, i jest to słownik , więc klucz jest tutaj również typem wartości. – Razzie

18

Słownik generuje wyjątek KeyNotFound w przypadku, gdy słownik nie zawiera klucza.

Zgodnie z sugestią, odpowiednim środkiem ostrożności jest ContainsKey. TryGetValue jest również skuteczny.

Dzięki temu słownik może efektywniej przechowywać wartość null. Bez zachowywania się w ten sposób, sprawdzenie zerowego wyniku z operatora [] wskaże albo wartość pustą, albo nieistnienie klucza wejściowego, co nie jest dobre.

+0

Dodatkowe informacje można znaleźć na stronie MSDN: http://msdn.microsoft.com/en-gb/library/9tee9ht2.aspx – cyberzed

-1

Klasa pomocnik jest przydatny:

public static class DictionaryHelper 
{ 
    public static TVal Get<TKey, TVal>(this Dictionary<TKey, TVal> dictionary, TKey key, TVal defaultVal = default(TVal)) 
    { 
     TVal val; 
     if(dictionary.TryGetValue(key, out val)) 
     { 
      return val; 
     } 
     return defaultVal; 
    } 
} 
Powiązane problemy