2009-08-26 5 views
63

J'ai eu des difficultés à articuler les différences entre ILookup<TKey, TVal> et IGrouping<TKey, TVal>, et je suis curieux si je comprends bien maintenant. LINQ a aggravé le problème en produisant des séquences de IGrouping articles tout en me donnant une méthode d'extension ToLookup. Donc, il me semblait qu'ils étaient identiques jusqu'à ce que je regarde de plus près.ILookup <TKey, TVal> vs IGrouping <TKey, TVal>

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

ce qui équivaut à:

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

qui ressemble beaucoup:

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

Ai-je raison dans les analogies suivantes?

  1. Un IGrouping<TKey, TVal> est un seul groupe (par exemple une séquence à clé), analogue à KeyValuePair<TKey, TVal> dont la valeur est en fait une séquence d'éléments (plutôt que d'un seul élément)
  2. Un IEnumerable<IGrouping<TKey, TVal>> est une séquence de ceux (similaire à ce que vous obtenez lorsque vous parcourez un IDictionary<TKey, TVal>
  3. un ILookup<TKey, TVal> est plus comme un IDictionary<TKey, TVal> où la valeur est en fait une suite d'éléments

Répondre

63

Oui, tous ceux qui sont correc t.

Et ILookup<TKey, TValue> étend également IEnumerable<IGrouping<TKey, TValue>> afin que vous puissiez parcourir toutes les paires clé/collection ainsi que (ou au lieu de) simplement rechercher des clés particulières. Je pense fondamentalement à ILookup<TKey,TValue> comme étant IDictionary<TKey, IEnumerable<TValue>>. N'oubliez pas que ToLookup est une opération «faites-le maintenant» (exécution immédiate) alors qu'une GroupBy est différée. Comme il arrive, avec la façon dont "pull LINQ" fonctionne, quand vous commencez à tirer IGrouping s du résultat d'un GroupBy, il doit lire toutes les données de toute façon (parce que vous ne pouvez pas changer de groupe à mi-chemin) alors que dans d'autres implémentations il peut être capable de produire un résultat de streaming. (Il le fait dans LINQ Push, je m'attendrais à ce que LINQ to Events soit le même.)

+0

Merci pour la réponse. Je n'ai jamais pensé à Linq en termes de push/pull avant. Quand je suis allé à Google, je suis tombé sur l'un de vos blogs, donc je vais vérifier cela. Cela semble être une façon intéressante d'y penser. – mckamey

+0

Je pense toujours que ces différences ne justifient pas 2 interfaces différentes. Je pense que le concepteur de la bibliothèque aurait dû choisir une seule interface.Peut-être juste un goût personnel qui est ici quelque chose de pas assez explicite. – rudimenter

+0

Est-ce moi ou y at-il une certaine confusion avec GroupBy vs GroupJoin? Ce ne sont que des liens conceptuels. Peut-être que c'est juste une faute de frappe dans la réponse si. – sehe

8

Il y a une autre différence importante entre ILookup et IDictionary: le premier impose l'immuabilité dans le sens où il n'y a pas de méthodes pour changer les données (sauf lorsque le consommateur effectue un casting explicite). En revanche, IDictionary a des méthodes comme "Ajouter" qui permettent de changer les données. Ainsi, du point de vue de la programmation fonctionnelle et/ou de la programmation parallèle, ILookup est plus agréable. (Je souhaite seulement qu'il y ait aussi une version de ILookup qui attribue une seule valeur à une clé plutôt qu'à un groupe.)

(Au fait, il convient de souligner que la relation entre IEnumerable et IList est quelque peu similaire à la un entre ILookup et IDictionary - le premier est immuable, le dernier n'est pas.)

+3

Pourquoi voudriez-vous un 'ILookup' qui a seulement une valeur d'un seul élément plutôt qu'un groupe? C'est ce qu'est un 'Dictionary' - ou un' ReadOnlyDictionary' ou 'IReadOnlyDictionary' si vous voulez qu'il soit immuable. – ErikE

Questions connexes