Ответ 1
Отслеживание документации MSDN, Ковариация и контравариантность в общих целях были внедрены в .NET Framework 4 До этого было IEnumerable<T>
с тех пор .NET Framework 2.0 до .NET Framework 3.5. Затем в .NET Framework 4.0 мы можем видеть IEnumerable<out T>
с параметром типа T
как ковариацией.
IGrouping<TKey, TElement>
и ILookup<TKey, TElement>
существуют с .NET Framework 3.5. В .NET Framework 4.0 первая была обновлена до IGrouping<out TKey, out TElement>
, но последняя была опущена без указания причины.
TKey
не может быть ковариантным, поскольку реализации Contains(TKey)
и this[TKey]
предотвращают это.
Что касается TElement
, вопрос не ясен. Я не верю, что дизайнеры просто пропустили это. Возможно, причина лежит в планах на будущее. Или они хотели предотвратить что-то вроде ниже, но я не знаю, почему:
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).
Есть и другие авторы, которые обращают внимание на эту проблему:
Следует отметить, что хотя IGrouping является ковариантным в TKey и TElement, ILookup инвариантен в обоих параметрах своего типа. Хотя TKey должен быть инвариантным, было бы разумно, чтобы TElement был ковариантным