suggest change

When is an IEnumerable<T> a subtype of a different IEnumerable<T1>? When T is a subtype of T1. IEnumerable is covariant in its T parameter, which means that IEnumerable’s subtype relationship goes in the same direction as T’s.

class Animal { /* ... */ }
class Dog : Animal { /* ... */ }

IEnumerable<Dog> dogs = Enumerable.Empty<Dog>();
IEnumerable<Animal> animals = dogs;  // IEnumerable<Dog> is a subtype of IEnumerable<Animal>
// dogs = animals;  // Compilation error - IEnumerable<Animal> is not a subtype of IEnumerable<Dog>

An instance of a covariant generic type with a given type parameter is implicitly convertible to the same generic type with a less derived type parameter.

This relationship holds because IEnumerable produces Ts but doesn’t consume them. An object that produces Dogs can be used as if it produces Animals.

Covariant type parameters are declared using the out keyword, because the parameter must be used only as an output.

interface IEnumerable<out T> { /* ... */ }

A type parameter declared as covariant may not appear as an input.

interface Bad<out T>
    void SetT(T t);  // type error

Here’s a complete example:

using NUnit.Framework;
namespace ToyStore
   enum Taste { Bitter, Sweet };

   interface IWidget
      int Weight { get; }

   interface IFactory<out TWidget>
       where TWidget : IWidget
      TWidget Create();

   class Toy : IWidget
      public int Weight { get; set; }
      public Taste Taste { get; set; }

   class ToyFactory : IFactory<Toy>
      public const int StandardWeight = 100;
      public const Taste StandardTaste = Taste.Sweet;

      public Toy Create() { return new Toy { Weight = StandardWeight, Taste = StandardTaste }; }

   public class GivenAToyFactory
      public static void WhenUsingToyFactoryToMakeWidgets()
         var toyFactory = new ToyFactory();

         //// Without out keyword, note the verbose explicit cast:
         // IFactory<IWidget> rustBeltFactory = (IFactory<IWidget>)toyFactory;

         // covariance: concrete being assigned to abstract (shiny and new)
         IFactory<IWidget> widgetFactory = toyFactory;
         IWidget anotherToy = widgetFactory.Create();
         Assert.That(anotherToy.Weight, Is.EqualTo(ToyFactory.StandardWeight)); // abstract contract
         Assert.That(((Toy)anotherToy).Taste, Is.EqualTo(ToyFactory.StandardTaste)); // concrete contract

Feedback about page:

Optional: your email if you want me to get back to you:

Table Of Contents