Indeksator do słownika zgłasza wyjątek, jeśli brakuje klucza. Czy istnieje implementacja IDictionary, która zamiast tego zwróci wartość default (T)?
Wiem o metodzie „TryGetValue”, ale nie da się jej użyć z linq.
Czy to skutecznie zrobi to, czego potrzebuję ?:
myDict.FirstOrDefault(a => a.Key == someKeyKalue);
Nie sądzę, żeby tak było, ponieważ myślę, że będzie iterować klucze zamiast używać wyszukiwania skrótu.
c#
.net
hash
dictionary
TheSoftwareJedi
źródło
źródło
Odpowiedzi:
Rzeczywiście, to wcale nie będzie skuteczne.
Zawsze możesz napisać metodę rozszerzenia:
Lub z C # 7.1:
To używa:
źródło
return (dictionary.ContainsKey(key)) ? dictionary[key] : default(TValue);
System.Collections.Generic.CollectionExtensions
, ponieważ właśnie próbowałem i jest.Noszenie tych metod rozszerzeń może pomóc.
źródło
Func<K, V>
.Jeśli ktoś używa .net core 2 i nowszych (C # 7.X), wprowadzana jest klasa CollectionExtensions i może użyć metody GetValueOrDefault , aby uzyskać wartość domyślną, jeśli klucza nie ma w słowniku.
źródło
Collections.Specialized.StringDictionary
zapewnia wynik niebędący wyjątkiem podczas wyszukiwania wartości brakującego klucza. Domyślnie wielkość liter nie jest rozróżniana.Ostrzeżenia
Jest ważny tylko do wyspecjalizowanych zastosowań i - ponieważ został zaprojektowany przed typami ogólnymi - nie ma bardzo dobrego modułu wyliczającego, jeśli chcesz przejrzeć całą kolekcję.
źródło
Jeśli używasz .Net Core, możesz użyć metody CollectionExtensions.GetValueOrDefault . To jest to samo, co implementacja podana w zaakceptowanej odpowiedzi.
źródło
źródło
Można zdefiniować interfejs dla funkcji wyszukiwania kluczy w słowniku. Prawdopodobnie zdefiniowałbym to jako coś takiego:
Wersja z kluczami nieogólnymi pozwoliłaby kodowi, który używał kodu przy użyciu typów kluczy innych niż strukturalne, aby umożliwić dowolną wariancję klucza, co nie byłoby możliwe w przypadku parametru typu ogólnego. Nie powinno się pozwalać na używanie mutable
Dictionary(Of Cat, String)
jako mutable,Dictionary(Of Animal, String)
ponieważ ta ostatnia na to pozwalaSomeDictionaryOfCat.Add(FionaTheFish, "Fiona")
. Ale nie ma nic złego w używaniu mutableDictionary(Of Cat, String)
jako niezmiennegoDictionary(Of Animal, String)
, ponieważSomeDictionaryOfCat.Contains(FionaTheFish)
powinno być uważane za doskonale sformułowane wyrażenie (powinno zwracaćfalse
, bez konieczności przeszukiwania słownika, niczego, co nie jest typuCat
).Niestety, jedynym sposobem, w jaki można faktycznie użyć takiego interfejsu, jest umieszczenie
Dictionary
obiektu w klasie implementującej interfejs. Jednak w zależności od tego, co robisz, taki interfejs i możliwe warianty mogą sprawić, że będzie to warte wysiłku.źródło
Jeśli używasz ASP.NET MVC, możesz wykorzystać klasę RouteValueDictionary, która wykonuje to zadanie.
źródło
To pytanie pomogło potwierdzić, że
TryGetValue
graFirstOrDefault
tutaj rolę.Jedną z interesujących funkcji języka C # 7, o którym chciałbym wspomnieć, jest funkcja zmiennych wyjściowych, a jeśli dodasz operator warunkowy zerowy z C # 6 do równania, kod może być znacznie prostszy bez konieczności stosowania dodatkowych metod rozszerzających.
Wadą tego jest to, że nie da się zrobić wszystkiego w ten sposób;
Jeśli potrzebowalibyśmy / chcielibyśmy to zrobić, powinniśmy zakodować jedną metodę rozszerzenia, taką jak Jon's.
źródło
Oto wersja @ JonSkeet dla świata C # 7.1, która pozwala również na przekazanie opcjonalnej wartości domyślnej:
Bardziej wydajne może być posiadanie dwóch funkcji, aby zoptymalizować przypadek, do którego chcesz zwrócić
default(TV)
:Niestety C # nie ma (jeszcze?) Operatora przecinka (lub operatora C # 6 proponowanego średnika), więc musisz mieć rzeczywistą treść funkcji (sap!) Dla jednego z przeciążeń.
źródło
Użyłem hermetyzacji, aby stworzyć IDictionary o zachowaniu bardzo podobnym do mapy STL , dla tych z Was, którzy znają c ++. Dla tych, którzy nie są:
TL / DR - SafeDictionary jest napisany tak, aby nigdy nie zgłaszać wyjątków w żadnych okolicznościach, innych niż perwersyjne scenariusze , takie jak brak pamięci na komputerze (lub pożar). Robi to, zastępując Add zachowaniem AddOrUpdate i zwracając wartość default zamiast wyrzucania NotFoundException z indeksatora.
Oto kod:
źródło
Od .NET core 2.0 możesz używać:
źródło
A co z tym jednowierszowym, który sprawdza, czy klucz jest obecny,
ContainsKey
a następnie zwraca normalnie pobraną wartość lub wartość domyślną za pomocą operatora warunkowego?Nie ma potrzeby implementowania nowej klasy Dictionary, która obsługuje wartości domyślne, po prostu zamień instrukcje wyszukiwania na krótką linię powyżej.
źródło
Sprawdzanie
TryGetValue
i zwracanie wartości domyślnej może być jednoliniowe, jeśli tak jestfalse
.myKey = "One"
=>value = 1
myKey = "two"
=>value = 100
myKey = "Four"
=>value = 4
Wypróbuj online
źródło
Nie, ponieważ w przeciwnym razie skąd znasz różnicę, gdy klucz istnieje, ale zapisał wartość null? To może być znaczące.
źródło