我在看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方法。

10-04 14:03