What are covariance and contravariance in C# generics?

Answer

Variance describes how generic types relate when their type arguments are related by inheritance. Covariance (out): allows using a more derived type than originally specified. IEnumerable<Dog> can be assigned to IEnumerable<Animal> (because IEnumerable<T> is out T — read-only, producers). interface ICovariant<out T> { T GetValue(); }T only appears in output positions. Contravariance (in): allows using a less derived type. Action<Animal> can be assigned to Action<Dog> (because an action that handles any Animal can handle a Dog). interface IContravariant<in T> { void Process(T item); }T only appears in input positions. Built-in examples: IEnumerable<out T>, IReadOnlyList<out T> (covariant), Action<in T>, IComparer<in T> (contravariant), Func<in T, out TResult> (both). Only interfaces and delegates support variance annotations (not classes/structs).