c# .net linq generics covariance

c# - ¿No debería ILookup<TKey, TElement>(declararse) covariante en TElement?



.net linq (1)

La definición System.Linq.ILookUp lee

interface ILookup<TKey, TElement> : IEnumerable<IGrouping<TKey, TElement>>, IEnumerable { int Count { get; } IEnumerable<TElement> this[TKey key] { get; } bool Contains(TKey key); }

Como IEnumerable es covariante en IGrouping <TKey, TElement>, IGrouping <TKey, TElement> es covariant en TElement y la interfaz solo expone a TElement como un tipo de retorno, supongo que ILookup también es covariante en TElement. De hecho, la definición

interface IMyLookup<TKey, out TElement> : IEnumerable<IGrouping<TKey, TElement>>, IEnumerable { int Count { get; } IEnumerable<TElement> this[TKey key] { get; } bool Contains(TKey key); }

Se compila sin problemas.

Entonces, ¿cuál podría ser la razón por la que falta la palabra clave de salida en la definición original? ¿Podría añadirse futuras versiones de Linq?


El seguimiento de la documentación de MSDN, Covariance y Contravariance en Genéricos se introdujeron en .NET Framework 4 Anteriormente, existía IEnumerable<T> desde .NET Framework 2.0 hasta .NET Framework 3.5. Luego, en .NET Framework 4.0 podemos ver IEnumerable<out T> con el tipo de parámetro T como covarianza.

IGrouping<TKey, TElement> e ILookup<TKey, TElement> existen desde .NET Framework 3.5. En .NET Framework 4.0, el primero se ha actualizado a IGrouping<out TKey, out TElement> pero el último se ha omitido sin especificar el motivo.

TKey no puede ser covariante, ya que las implementaciones de Contains(TKey) y this[TKey] impiden.

Con respecto a TElement el tema no está claro. No creo que los diseñadores se lo hayan perdido. Quizás la causa esté en los planes para el futuro. O querían evitar algo como lo de abajo, pero no sé por qué:

string[] strings = new[] {"a", "a", "b", "b", "b", "c"}; ILookup<string, string> lookup = strings.ToLookup(s => s); // Valid. ILookup<string, object> lookup = strings.ToLookup(s => s); // Now invalid, but would correct if TElement was covariant (out TElement).

También hay otros autores, que prestan atención a ese tema:

ToLookup :

Un punto un poco extraño a tener en cuenta es que si bien IGrouping es covariante en TKey y TElement, ILookup es invariante en ambos parámetros de tipo. Si bien TKey tiene que ser invariante, sería razonable que TElement sea covariante.