2009-08-26 17 views
63

Mam problemy z wyartykułowaniem różnic między ILookup<TKey, TVal> i IGrouping<TKey, TVal>, i jestem ciekawy, czy rozumiem teraz poprawnie. LINQ pomógł rozwiązać ten problem, tworząc sekwencje elementów IGrouping, a także podając metodę rozszerzenia ToLookup. Czułem się, jakby były takie same, dopóki nie przyjrzałem się dokładniej.ILookup <TKey, TVal> Przeciw IGrouping

var q1 = 
    from n in N 
    group n by n.MyKey into g 
    select g; 
// q1 is IEnumerable<IGrouping<TKey, TVal>> 

co jest równoważne:

var q2 = N.GroupBy(n => n.MyKey, n => n); 
// q2 is IEnumerable<IGrouping<TKey, TVal>> 

który wygląda trochę jak:

var q3 = N.ToLookup(n => n.MyKey, n => n); 
// q3 is ILookup<TKey, TVal> 

Am I poprawić w następujących analogii?

  1. IGrouping<TKey, TVal> jest jedna grupa (tj Kluczowany sekwencji), analogicznie do KeyValuePair<TKey, TVal>, gdy wartość ta jest ciągiem elementów (raczej niż pojedynczy element)
  2. IEnumerable<IGrouping<TKey, TVal>> jest sekwencją tych (podobny do tego, co można uzyskać podczas iteracji nad IDictionary<TKey, TVal>
  3. ILookup<TKey, TVal> jest bardziej jak IDictionary<TKey, TVal> gdzie wartość jest faktycznie ciągiem elementów

Odpowiedz

63

Tak, wszystkie z nich są correc t.

I ILookup<TKey, TValue> również rozszerza IEnumerable<IGrouping<TKey, TValue>>, dzięki czemu można iterować nad wszystkimi parami klucz/kolekcja, jak również (lub zamiast) po prostu szukając poszczególnych kluczy.

W zasadzie myślę o ILookup<TKey,TValue> jako o IDictionary<TKey, IEnumerable<TValue>>.

Należy pamiętać, że ToLookup jest operacją "zrób to teraz" (natychmiastowe wykonanie), natomiast GroupBy jest odroczona. Jak to się dzieje, ze sposobem, w jaki działa "pull LINQ", kiedy zaczynasz ciągnąć IGrouping s z wyniku , to i tak musisz przeczytać wszystkie dane (ponieważ nie możesz przełączać grupy w połowie), podczas gdy w innych implementacjach może być w stanie wytworzyć wynik transmisji strumieniowej. (Działa w Push LINQ, spodziewałbym się, że LINQ do wydarzeń będzie taki sam.)

+0

Dzięki za odpowiedź. Nie natknąłem się na Linq pod względem push/pull. Kiedy poszedłem do Google, natknąłem się na jeden z twoich blogów, więc sprawdzę to. Brzmi jak ciekawy sposób na przemyślenie tego. – mckamey

+0

Nadal uważam, że te różnice nie uzasadniają 2 różnych interfejsów. Myślę, że projektant Biblioteki powinien zdecydować się na jeden interfejs.Może tylko osobisty gust, który tutaj jest czymś mało wyraźnym. – rudimenter

+0

Czy to ja, czy jest jakiś błąd z GroupBy vs GroupJoin? Są one tylko _związane konceptualnie. Być może jest to tylko literówka w odpowiedzi. – sehe

8

Jest jeszcze jedna ważna różnica między ILookup i IDictionary: pierwszy wymusza niezmienność w tym sensie, że nie ma tutaj żadnych metod zmiany danych (z wyjątkiem sytuacji, gdy konsument wykonuje wyraźną obsadę). Natomiast IDictionary ma takie metody, jak "Dodaj", które umożliwiają zmianę danych. Tak więc, z perspektywy programowania funkcjonalnego i/lub programowania równoległego, ILookup jest ładniejszy. (Szkoda tylko, że istniała również wersja ILookup, która przypisuje tylko jedną wartość do klucza, a nie do grupy.)

(Przy okazji warto zwrócić uwagę, że związek między IEnumerable i IList jest nieco podobny do jedna między ILookup i IDictionary - pierwsza jest niezmienna, druga nie.)

+3

Dlaczego chcesz "ILookup", który ma tylko wartość jednego elementu zamiast grupy? Tak właśnie jest "słownik" - lub "ReadOnlyDictionary" lub "IReadOnlyDictionary", jeśli chcesz, aby był niezmienny. – ErikE

Powiązane problemy