Covariance and Contravariance in C#
Andrea Angella
Technical Lead @ Redgate Software | ?Former Six-Times MVP on C# | ?? Grow Software Engineering Leaders | ?? Trainer, Mentor and Coach @ productivecsharp.com | ?? Host of The Productive C# Podcast | ?? Books Reader
Originally published on the Productive C# blog in 2013.
Covariance
Covariance for generics interfaces is a new feature introduced with the version 4 of the C# language.
The definition for Generics Interfaces
Assuming A is convertible to B,??X is covariant if X<A> is implicitly convertible to X<B>
or similarly
X is covariant if X<A> can be cast to X<B> if B subclasses A
From C# 4, generic interfaces support covariance for type parameters marked with the?out?modifier. This modifier ensures that covariance with interfaces is fully type-safe.
Covariance in interfaces is something that is typically consumed. It’s less common that you need?to write variant interfaces.
The implementation of IEnumerable in the framework has been changed using the out modifier and this makes all the collections in the base class library covariant.
public interface IEnumerable<out T> : IEnumerable
Example
Suppose that we have two classes in a?inheritance relationship.
Thanks to this new feature of the language, the following code compiles and works as expected.
If you use a previous version of C# the code does not compile and generates a build error.
It is worth noting that previous versions of C# already supported it in arrays and delegates.
If you like this article and interested in taking the next step to master C#, join my?free course on Modern C# 11.
Contravariance
Contravariance is a new feature introduced with the version 4 of the C# language.
The definition
Assuming A is implicitly convertible to B,??X?is contravariant when?X<B>?is implicitly convertible to?X<A>?
or similarly
X is contravariant if X<B> can be cast to X<A> if B subclasses A
From C# 4, generic interfaces support it for type parameters marked with the?in?modifier.?This is supported when the generic type parameter only appears in input positions, designed with the in modifier.
While covariance seems intuitive, contravariance seems useless and wrong.
However, it makes sense and there are situations when is useful.
One example is the IEquatityComparer<T> interface that has been changed using the in modifier.
public interface IEqualityComparer<in T>
Example
Suppose that we have the following classes.
Thanks to contravariance the following code compiles and works as expected.
If you use a previous version of C# the code does not compile and generates a build error.
If you like this article and interested in taking the next step to master C#, join my?free course on Modern C# 11.
.Net Full Stack Developer presso EUROGED - Gestione Elettronica Documentale
1 年A while ago I tried to talk to some colleagues about it and they looked at me like I was an alien! ??