2009-08-26 11 views
63

He estado teniendo problemas para expresar las diferencias entre ILookup<TKey, TVal> y IGrouping<TKey, TVal>, y tengo curiosidad si lo entiendo correctamente ahora. LINQ complicó el problema al producir secuencias de IGrouping elementos mientras que también me dio un método de extensión ToLookup. Entonces sentí que eran lo mismo hasta que miré más de cerca.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>> 

lo que equivale a:

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

que se parece mucho a:

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

Estoy en lo correcto en las siguientes analogías?

  1. Un IGrouping<TKey, TVal> es un solo grupo (es decir, una secuencia por clave), análoga a KeyValuePair<TKey, TVal> donde el valor es en realidad una secuencia de elementos (en lugar de un solo elemento)
  2. Un IEnumerable<IGrouping<TKey, TVal>> es una secuencia de los (similar a lo que se obtiene cuando se repite más de una IDictionary<TKey, TVal>
  3. un ILookup<TKey, TVal> es más como un IDictionary<TKey, TVal> donde el valor es en realidad una secuencia de elementos

Respuesta

63

Sí, todos esos son correc t.

Y ILookup<TKey, TValue> también se extiende IEnumerable<IGrouping<TKey, TValue>> para que pueda iterar sobre todos los pares clave/colección, así como (o en lugar de) solo buscar teclas particulares.

Básicamente creo que ILookup<TKey,TValue> es como IDictionary<TKey, IEnumerable<TValue>>.

Tenga en cuenta que ToLookup es una operación "hágalo ahora" (ejecución inmediata) mientras que se difiere un GroupBy. Como sucede, con la forma en que "pull LINQ" funciona, cuando comienzas a sacar IGrouping s del resultado de GroupBy, tiene que leer todos los datos de todos modos (porque no puedes cambiar de grupo a medio camino) mientras que en otras implementaciones puede ser capaz de producir un resultado de transmisión. (Lo hace en Push LINQ; esperaría que LINQ to Events sea el mismo.)

+0

Gracias por la respuesta. No me he encontrado pensando en Linq en términos de empujar/tirar antes. Cuando fui a Google, me encontré con uno de sus blogs, así que lo verificaré. Suena como una forma interesante de pensar sobre eso. – mckamey

+0

Todavía pienso que estas diferencias no justifican 2 interfaces diferentes. Creo que el diseñador de la biblioteca debería haber decidido una sola interfaz.Tal vez solo un gusto personal que aquí es algo no lo suficientemente explícito. – rudimenter

+0

¿Soy yo o hay alguna confusión con GroupBy frente a GroupJoin? Esos solo están relacionados conceptualmente. Sin embargo, es solo un error en la respuesta. – sehe

8

Hay otra diferencia importante entre ILookup e IDictionary: la primera impone la inmutabilidad en el sentido de que aquí no hay métodos para cambiar los datos (excepto cuando el consumidor realiza un lanzamiento explícito). Por el contrario, IDictionary tiene métodos como "Agregar" que permiten cambiar los datos. Entonces, desde la perspectiva de la programación funcional y/o programación paralela, ILookup es más agradable. (Ojalá también hubiera una versión de ILookup que asigna un solo valor a una clave en lugar de un grupo.)

(Por cierto, parece que vale la pena señalar que la relación entre IEnumerable e IList es similar a la uno entre ILookup e IDictionary - el primero es inmutable, el último no).

+3

¿Por qué querrías un 'ILookup' que tiene solo un valor de un solo elemento en lugar de un grupo? Eso es lo que un 'Diccionario' es, o un' ReadOnlyDictionary' o 'IReadOnlyDictionary' si quieres que sea inmutable. – ErikE

Cuestiones relacionadas