Variance allows to replace a type with a less-derived (covariance: derived → base) type or a more-derived type (contravariance: base → derived).
Covariance enable implicit reference conversion for array types, delegate types, and generic type arguments. It preserves assignment compatibility and contravariance reverses it.
Contravariance
Since .NET Framework 4, C# supports covariance and contravariance in generic interfaces and delegates and allows for implicit conversion of generic type parameters.
Assignment compatibility
Allow an object of a more derived type (child class, ex: string) to be assigned to an object of a less derived type (parent class, ex: object).
strings = "test";
objecto = s;
Covariance
Allow a generic object of child class type (ex: string) to be assigned to a generic object of parent class type (ex: object).
It works only with covariant interface
varderiveds = newList<Derived>();
List<Base> bases = strings; // Cannot convert type List<Base> to List<Derived> because List<T> is invariantIList<Base> bases = strings; // Cannot implicitly convert type List<Base> to IList<Derived> because IList<T> is invariantvarbases = (IList<Base>)deriveds; // at execution, Unable to cast List<Derived> to type IList<Base>IEnumerable<Base> bases = deriveds; // IEnumerable<T> is covariantIReadOnlyList<Base> bases = deriveds; // IReadOnlyList<T> is covariantIReadOnlyCollection<Base> bases = deriveds; // IReadOnlyCollection<T> is covariant