Aller au contenu

Covariance out T et contravariance in T

Contexte : La covariance (out T) permet d’utiliser un type plus dérivé que celui spécifié (pour les valeurs de retour). La contravariance (in T) permet d’utiliser un type moins dérivé (pour les paramètres d’entrée). Cela permet l’assignation polymorphique des interfaces génériques.

using System;
using System.Collections.Generic;
// Covariance : T est en position de retour (out)
public interface IProducteur<out T>
{
T Produire();
}
// Contravariance : T est en position d'entrée (in)
public interface IConsommateur<in T>
{
void Consommer(T item);
}
public class Animal { }
public class Chien : Animal { }
public class ProducteurChien : IProducteur<Chien>
{
public Chien Produire() => new Chien();
}
public class ConsommateurAnimal : IConsommateur<Animal>
{
public void Consommer(Animal animal)
{
Console.WriteLine($"Consomme {animal.GetType().Name}");
}
}
class Program
{
static void Main()
{
// Covariance : IProducteur<Chien> peut être assigné à IProducteur<Animal>
IProducteur<Animal> producteur = new ProducteurChien();
Animal animal = producteur.Produire();
Console.WriteLine($"Produit: {animal.GetType().Name}");
// Contravariance : IConsommateur<Animal> peut être assigné à IConsommateur<Chien>
IConsommateur<Chien> consommateur = new ConsommateurAnimal();
consommateur.Consommer(new Chien());
}
}
Fenêtre de terminal
dotnet run
Produit: Chien
Consomme Chien
  • out T signifie que T ne peut être utilisé qu’en sortie (retour de méthode, propriété get).
  • in T signifie que T ne peut être utilisé qu’en entrée (paramètres de méthode, propriété set).
  • Les types valeur ne supportent pas la variance.

IEnumerable<out T> – Covariant, donc on peut passer List<Chien> à une méthode qui attend IEnumerable<Animal>.
Action<in T> – Contravariant.
Voir documentation .NET sur la covariance/contravariance.