Shouldn't ILookup<TKey, TElement> be (declared) covariant in TElement?

心已入冬 提交于 2019-12-21 03:20:08

问题


The definition System.Linq.ILookUp reads

interface ILookup<TKey, TElement> : IEnumerable<IGrouping<TKey, TElement>>, IEnumerable {
    int Count {
        get;
    }

    IEnumerable<TElement> this[TKey key] {
        get;
    }

    bool Contains(TKey key);
}

Since IEnumerable is covariant in IGrouping<TKey, TElement>, IGrouping<TKey, TElement> is covariant in TElement and the interface only exposes TElement as a return type, I would assume that ILookup is also covariant in TElement. Indeed, the definition

interface IMyLookup<TKey, out TElement> : IEnumerable<IGrouping<TKey, TElement>>, IEnumerable {
    int Count {
        get;
    }

    IEnumerable<TElement> this[TKey key] {
        get;
    }

    bool Contains(TKey key);
}

compiles without problems.

So, what might be the reason why the out keyword is missing in the original definition? Might it be added future versions of Linq?


回答1:


Tracking the MSDN documentation, Covariance and Contravariance in Generics have been introduced in .NET Framework 4 Prior to that, there was IEnumerable<T> since the .NET Framework 2.0 up to .NET Framework 3.5. Then in .NET Framework 4.0 we can see IEnumerable<out T> with type parameter T as covariance.

IGrouping<TKey, TElement> and ILookup<TKey, TElement> have existed since .NET Framework 3.5. In .NET Framework 4.0 the former has been updated to IGrouping<out TKey, out TElement> but the latter has been omitted without specifying the reason.

TKey can't be covariant since implementations of Contains(TKey) and this[TKey] prevent that.

With regard to TElement the issue is not clear. I don't believe that designers just missed it. Perhaps cause lies in the plans for the future. Or they wanted to prevent something like the below, but I don't know why:

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).

There are also other authors, that pay attention to that issue:

ToLookup:

One slightly odd point to note is that while IGrouping is covariant in TKey and TElement, ILookup is invariant in both of its type parameters. While TKey has to be invariant, it would be reasonable for TElement to be covariant



来源:https://stackoverflow.com/questions/14883727/shouldnt-ilookuptkey-telement-be-declared-covariant-in-telement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!