2008-10-31 17 views
15

Obecnie używamC# słowniki ValueOrNull/ValueorDefault

var x = dict.ContainsKey(key) ? dict[key] : defaultValue 

Chciałbym jakiś sposób, aby mieć słownika [key] zwróci wartość null kluczy nonexistant, więc mogę napisać coś

var x = dict[key] ?? defaultValue; 

to również jest częścią zapytań linq itp., Więc wolałbym rozwiązania jednolinijkowe.

+0

Aktualne odpowiedzi są poprawne i zobacz także [moje podobne pytanie] (http://stackoverflow.com/questions/6214975), które jest bardziej dyskusyjne. Jednak powinieneś unikać 'dict.ContainsKey (key)? dict [key] 'jak przeglądasz słownik dwa razy, raz dla' ContainsKey' i znowu dla indexera '[]'. 'TryGetValue' jest brzydka i nie jest wbudowana, ale jest to pojedyncza operacja. – Keith

Odpowiedz

21

Z metodę rozszerzenia:

public static class MyHelper 
{ 
    public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dic, 
              K key, 
              V defaultVal = default(V)) 
    { 
     V ret; 
     bool found = dic.TryGetValue(key, out ret); 
     if (found) { return ret; } 
     return defaultVal; 
    } 
    void Example() 
    { 
     var dict = new Dictionary<int, string>(); 
     dict.GetValueOrDefault(42, "default"); 
    } 
} 
+4

I d oferuje przeciążenie, które zwraca wartość domyślną (V) – Will

+4

W C# 4 można teraz ustawić domyślny parametr opcjonalny: V defaultVal = default (V). Wtedy nie musisz przekazywać wartości domyślnej, jeśli nie chcesz - jeśli wartość nie zostanie znaleziona, otrzymasz wartość domyślną dla typu V. – Tevin

+0

@ Tevin możesz podać link do msdn/article który dokumentuje to zachowanie? Nie jestem zaznajomiony z .NET 4, ale domyślny operator na typie odniesienia w .NET 3.5 zwraca wartość null i domyślnie na typ wartości zwraca wartość za pomocą konstruktora no-args. Wątpię, żeby to się zmieniło? – toong

6

Można użyć metody pomocnika:

public abstract class MyHelper { 
    public static V GetValueOrDefault<K,V>(Dictionary<K,V> dic, K key) { 
     V ret; 
     bool found = dic.TryGetValue(key, out ret); 
     if (found) { return ret; } 
     return default(V); 
    } 
} 

var x = MyHelper.GetValueOrDefault(dic, key); 
+0

Możesz także trywialnie uczynić tę metodę rozszerzenia, abyś mógł zrobić dict.GetValueOrDefault (klucz) – stevemegson

+0

Myślałem, że zrobił to na pierwszym miejscu ... Dziwne, że jedyną różnicą byłoby słowo kluczowe "to". – Will

+3

Możesz rzeczywiście uczynić to bezwarunkowym - po prostu zwróć ponownie po wywołaniu do TryGetValue. Będzie domyślnie (V), jeśli metoda zwróci false. –

0

nie jest po prostu TryGetValue(key, out value) czego szukasz? Cytowanie MSDN:

When this method returns, contains the value associated with the specified key, if the key is found; otherwise, the default value for the type of the value parameter. This parameter is passed uninitialized. 

z http://msdn.microsoft.com/en-us/library/bb347013(v=vs.90).aspx

+0

Szukałem jednoliniowego wyrażenia. Problem z 'TryGetValue' jest taki, że 1) jest stwierdzeniem. 2) wymaga poprzedniej deklaracji zmiennej "out". – Jimmy

4

Oto rozwiązanie „ostateczny”, w który jest on zaimplementowany jako metodę rozszerzenia, wykorzystuje IDictionary interfejs, zapewnia opcjonalną wartość domyślną, a jest napisane zwięźle.

public static TV GetValueOrDefault<TK, TV>(this IDictionary<TK, TV> dic, TK key, 
    TV defaultVal=default(TV)) 
{ 
    TV val; 
    return dic.TryGetValue(key, out val) 
     ? val 
     : defaultVal; 
}