c# - net - ILookup<TKey, TVal> vs. IGrouping<TKey, TVal>
linq group join (2)
He estado teniendo problemas para expresar las diferencias entre ILookup<TKey, TVal>
e IGrouping<TKey, TVal>
, y tengo curiosidad si ahora lo entiendo correctamente. LINQ IGrouping
el problema al producir secuencias de elementos IGrouping
al mismo tiempo que me daba un método de extensión ToLookup
. Entonces sentí que eran lo mismo hasta que miré más de cerca.
var q1 =
from n in N
group n by n.MyKey into g
select g;
// q1 is IEnumerable<IGrouping<TKey, TVal>>
Lo cual es equivalente 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?
- Un
IGrouping<TKey, TVal>
es un único grupo (es decir, una secuencia con clave), análogo aKeyValuePair<TKey, TVal>
donde el valor es en realidad una secuencia de elementos (en lugar de un solo elemento) - Un
IEnumerable<IGrouping<TKey, TVal>>
es una secuencia de esos (similar a lo que obtienes al iterar sobre unIDictionary<TKey, TVal>
- Un
ILookup<TKey, TVal>
es más como unIDictionary<TKey, TVal>
donde el valor es en realidad una secuencia de elementos
Hay otra diferencia importante entre ILookup e IDictionary: el primero impone la inmutabilidad en el sentido de que 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 a un grupo).
(Por cierto, parece que vale la pena señalar que la relación entre IEnumerable e IList es similar a la de ILookup e IDictionary: la primera es inmutable, la última no).
Sí, todos esos son correctos.
Y ILookup<TKey, TValue>
también extiende IEnumerable<IGrouping<TKey, TValue>>
para que pueda iterar sobre todos los pares clave / colección, así como (o en lugar de) solo buscar claves 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 un GroupBy
se difiere. Como sucede, con la forma en que "pull LINQ" funciona, cuando comienzas a sacar IGrouping
s del resultado de un 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).