我在看iorderedenumerable的声明,我惊讶地发现它在telement类型参数中不是协变的。
public interface IOrderedEnumerable<TElement> : IEnumerable<TElement>, IEnumerable
{
IOrderedEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending);
}
它没有协变的原因是什么?
最佳答案
这是一个疏忽,它被固定在.NET内核中。这里是关于这个的(封闭的)issue,这里是修复它的pull request。
我认为它在完整的.net版本中没有得到修复,因为这是一个突破性的变化。例如(idea取自这个answer,它是关于另一个突破性的变化,但也适用于这里):
public class Base
{
public void DoSomething(IOrderedEnumerable<string> strings)
{
Console.WriteLine("Base");
}
}
public class Derived : Base
{
public void DoSomething(IOrderedEnumerable<object> objects)
{
Console.WriteLine("Derived");
}
}
然后你打电话
Derived d = new Derived();
d.DoSomething(new List<string>().OrderBy(c => c));
如果
IOrderedEnumerable
不是协变的-Base
方法将被调用。现在假设我们将其改为协变。当我们下次编译此代码时,会突然调用Derived
方法。