Back to results for “Generics”
C# › Generics

What is covariance ('out T') and contravariance ('in T') in generic interfaces, and how does IEnumerable<out T> demonstrate covariance?

Intermediate

Answer

Covariance ('out T') allows a generic interface with a type parameter used only in OUTPUT positions (return values) to be treated as its LESS specific base type automatically — e.g., IEnumerable<Dog> can be used where IEnumerable<Animal> is expected, since you can only READ Dogs out of it as Animals safely; contravariance ('in T') is the reverse, for type parameters used only in INPUT positions.
IEnumerable<string> strings = new List<string> { "a", "b" };
IEnumerable<object> objects = strings; // OK! covariant: IEnumerable<out T> allows this

// Contravariance example:
Action<object> objectAction = obj => Console.WriteLine(obj);
Action<string> stringAction = objectAction; // OK! contravariant: Action<in T> allows this
Real-world example Understanding why you can assign an IEnumerable<Dog> directly to an IEnumerable<Animal>-typed variable without any explicit conversion.

Common follow-ups: Why can't a MUTABLE generic interface like IList<T> be covariant the same way IEnumerable<T> is?