Search code examples
c#covariance

Why the interface IOrderedEnumerable<T> isn't covariant in T?


I was Looking at the declaration of IOrderedEnumerable an I was suprised that it isn't covariant in it's TElement type parameter .

public interface IOrderedEnumerable<TElement> : IEnumerable<TElement>, IEnumerable
{
    IOrderedEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending);
}

What's the reason for which it was not made covariant ?


Solution

  • It's an oversight and that was fixed in .NET Core. Here is (closed) issue about that and here is pull request which fixes it.

    It's not getting fixed in full .NET version I think because that's a breaking change. For example (idea is taken from this answer which is about another breaking change, but applies here too):

    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");
        }
    }
    

    Then you call

    Derived d = new Derived();
    d.DoSomething(new List<string>().OrderBy(c => c));
    

    If IOrderedEnumerable is not covariant - Base method would be called. Now suppose we change that to covariant. When we next time compile this code, suddenly Derived method is called.