2013-04-23 16 views
7

Jeśli masz obiekt Dictionary<k, v> myDictionary, wówczas myDictionary.Values będzie typu Dictionary<k, v>.ValueCollection, a myDictionary.Keys będzie miał typ Dictionary<k, v>.KeyCollection. Nie mam pojęcia, dlaczego typ myDictionary.Values nie jest podobny do IEnumerable<v>, IList<v> lub coś innego.Jaki typ powinien zwrócić myCustomDictionary.Values?

Teraz, mając to na uwadze, jeśli utworzę niestandardowy rodzaj słownika; Dictionary2<k1, k2, v>, powinien myCustomDictionary.Values zwrócić IEnumerable<v> lub niestandardowe narzędzie ValueCollection? Co ważniejsze, dlaczego?

+2

Bardzo ciekawe pytanie :) –

Odpowiedz

5

Pamiętaj, że Dictionary<TKey, TValue>.ValueCollection w rzeczywistości implementuje ICollection<TValue>, a zatem także IEnumerable<TValue>.

Powodem nieruchomość jest wpisane droga to jest prawdopodobne, ze względu na wydajność: od metody tej klasy nie są wirtualne, można je dokładnie rozwiązany podczas JIT kompilacji, zamiast konieczności vtable wyszukiwań dla każdej metody zadzwoń w czasie wykonywania. To skutecznie usuwa jeden poziom indoktrysu z każdej metody, którą wywołujesz w kolekcji. (Daje to również JIT możliwość wstawiania tych wywołań metod!)

Oczywiście można w razie potrzeby przekonwertować obiekt na ICollection<TValue>, więc nie ma tu żadnej utraty funkcjonalności, tylko trochę (mikro) optymalizacji .

W twoim przypadku nie ma powodu, dla którego nie możesz zwrócić ICollection<TValue>, ale możesz zwrócić bardziej szczegółowy typ, jeśli chcesz. Jeśli tak, to trzeba będzie jawnie zaimplementować właściwość interfejsu IDictionary<TKey, TValue>.Values zaspokoić interfejs:

private ValueCollection valueCollection; 

public ValueCollection Values 
{ 
    get { return valueCollection; } 
} 

ICollection<TValue> IDictionary<TKey, TValue>.Values 
{ 
    get { return valueCollection; } 
} 

To właściwie oznacza, że ​​wszelkie korzyści wydajności będą tylko do konsumentów z klasy, jeśli są one za pomocą odniesienie wpisane jako twój typ kolekcji; nie będzie żadnej korzyści z wydajności, jeśli odwołamy się do IDictionary<TKey, TValue>, ponieważ będą musieli wybrać, ale mimo to uzyskać dostęp do twojego zbioru wartości przez ICollection<TValue>.

W swojej pracy nie stwierdziłem, że różnica w wydajności jest na tyle znacząca, aby zagwarantować zwrot czegoś bardziej konkretnego niż ICollection<TValue>. Pamiętaj: zawsze sprawdzaj i nigdy przedwcześnie nie optymalizuj.

+1

Co, ta odpowiedź zawiera wiele informacji. Wielkie dzięki, sir! – Tipx

+0

'Lista ' i 'Słownik ' to najczęściej używane implementacje 'IList ' i 'IDictionary '. W związku z tym zapobieganie niepotrzebnym wywołaniom wywołania interfejsu ma łączny wpływ na cały ekosystem .NET i przyczynia się do zwiększenia mocy urządzenia mobilnego, której Java nigdy nie będzie w stanie dotknąć (z powodu nadużywania zastępowalnych metod w klasach infrastruktury). –

1

Dictionary<k, v>.ValueCollection implementuje IEnumerable<v> i Dictionary<k, v>.KeyCollection implementuje IEnumerable<k>. To nie tak, że zwracane wyniki nie są przeliczalne.

Powoduje to, że zwracając rzeczywistą klasę, która implementuje IEnumerable, zamiast wpisywać wynik jako IEnumerable, mogą one również zawierać dodatkowe funkcje. Na przykład obie kolekcje mają właściwość Count, która nie jest łatwo dostępna z poziomu dowolnego IEnumerable.

+2

Należy zauważyć, że 'ICollection ' ma właściwość Count, a 'IDictionary .Values' zwraca" ICollection ". Tak więc * dowolna * implementacja 'IDictionary ' * musi * zwrócić obiekt 'Values', który i tak obsługuje właściwość' Count'. Bardziej specyficzny typ 'Dictionary .Values' w żaden sposób nie zapewnia dodatkowej funkcjonalności, którą widzę. – cdhowie

Powiązane problemy