0Pricing
C# Academy · Leçon

Variance (in/out) avec les interfaces et les délégués

Comprenez la variance en C# : out pour les producteurs (covariance) et in pour les consommateurs (contravariance), sur les interfaces et les délégués.

Variance (in/out) avec les interfaces et les délégués est une leçon C# Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 3. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage C# Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours C# Academy comprend 3 leçons au total.

Vue d’ensemble de la variance

La variance permet aux interfaces et délégués génériques de fonctionner avec l’héritage.

  • out = covariance (producteur)
  • in = contravariance (consommateur)
  • Elle est sûre lorsque l’API produit uniquement ou consomme uniquement T

Démonstration de la covariance

IEnumerable<out T> est covariant : une séquence de chats peut être utilisée là où une séquence d’animaux est attendue.

using System;
using System.Collections.Generic;

public class Animal { public virtual string Name() { return "animal"; } }
public class Cat : Animal { public override string Name() { return "cat"; } }

public class Program
{
  static void PrintAll(IEnumerable<Animal> animals)
  {
    foreach (Animal a in animals)
    {
      Console.WriteLine(a.Name());
    }
  }

  public static void Main(string[] args)
  {
    List<Cat> cats = new List<Cat>();
    cats.Add(new Cat());
    // IEnumerable<Cat> -> IEnumerable<Animal> is allowed (out T)
    PrintAll(cats);
  }
}

Démonstration de la contravariance

IComparer<in T> est contravariant : un comparateur pour Animal fonctionne aussi pour Cat, car il ne fait que consommer T.

using System;
using System.Collections.Generic;

public class Animal { public string N; public Animal(string n){ N=n; } }
public class Cat : Animal { public Cat(string n) : base(n) {} }

// Comparer can compare any Animals
public class AnimalNameComparer : IComparer<Animal>
{
  public int Compare(Animal x, Animal y)
  {
    return string.Compare(x == null ? "" : x.N, y == null ? "" : y.N, StringComparison.Ordinal);
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    List<Cat> cats = new List<Cat>();
    cats.Add(new Cat("Miso"));
    cats.Add(new Cat("Ada"));
    // IComparer<Animal> can be used as IComparer<Cat> (in T)
    cats.Sort(new AnimalNameComparer());
    foreach (Cat c in cats) Console.WriteLine(c.N);
  }
}

Variance de delegate

Les types delegate sont eux aussi variants : Func<out TResult> (producteur) et Action<in T> (consommateur).

using System;

public class Animal { public virtual string Speak(){ return "???"; } }
public class Cat : Animal { public override string Speak(){ return "meow"; } }

public class Program
{
  static Animal MakeAnimal() { return new Animal(); }
  static void HandleAnimal(Animal a) { Console.WriteLine(a.Speak()); }

  public static void Main(string[] args)
  {
    // Func<Cat> can be used where Func<Animal> is expected? Yes, because TResult is out.
    Func<Animal> maker = new Func<Cat>(delegate { return new Cat(); });
    Console.WriteLine(maker().Speak());

    // Action<Animal> can be used where Action<Cat> is expected? Yes, because T is in.
    Action<Cat> catSink = new Action<Animal>(HandleAnimal);
    catSink(new Cat());
  }
}

Interfaces personnalisées avec variance

Règle de conception : marquez les paramètres réservés à la production avec out et ceux réservés à la consommation avec in afin d’autoriser des conversions sûres.

using System;

// Producer-only interface: out T
public interface ISource<out T>
{
  T Get();
}

// Consumer-only interface: in T
public interface ISink<in T>
{
  void Put(T item);
}

public class Animal { public string N; }
public class Cat : Animal { }

public class CatSource : ISource<Cat>
{
  public Cat Get() { return new Cat(); }
}

public class AnimalSink : ISink<Animal>
{
  public void Put(Animal a) { Console.WriteLine("Got animal"); }
}

public class Program
{
  public static void Main(string[] args)
  {
    ISource<Animal> animals = new CatSource(); // out T allows upcast
    ISink<Cat> cats = new AnimalSink();        // in T allows down-assign
    animals.Get();
    cats.Put(new Cat());
  }
}

Conseils sur la variance

Conseils :

  • Les paramètres out ne peuvent apparaître que dans des positions de sortie (types de retour, emplacements covariants).
  • Les paramètres in ne peuvent apparaître que dans des positions d’entrée (paramètres de méthode).
  • Ne mélangez pas production et consommation pour le même T lors de la déclaration de la variance.
  • La variance s’applique aux interfaces et aux types delegate, pas aux classes.

Mot-clé de covariance

Vérification rapide : quel mot-clé marque un paramètre de type covariant sur une interface ou un delegate ?

Récapitulatif

Récapitulatif : utilisez out pour les producteurs (covariance) et in pour les consommateurs (contravariance) sur les interfaces et les delegate. Concevez des interfaces de programmation à sens unique pour permettre des conversions sûres.

Questions Fréquemment Posées

La leçon « Variance (in/out) avec les interfaces et les délégués » est-elle gratuite ?

Oui — le texte complet de « Variance (in/out) avec les interfaces et les délégués » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours C# Academy, passe à CoddyKit PRO. Le cours C# Academy comprend 3 leçons au total.

Qu'est-ce que j'apprendrai dans « Variance (in/out) avec les interfaces et les délégués » ?

Comprenez la variance en C# : out pour les producteurs (covariance) et in pour les consommateurs (contravariance), sur les interfaces et les délégués. Tu pratiques C# Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer C# Academy ?

Aucune expérience préalable n'est requise. C# Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 3.

Combien de temps prend la leçon « Variance (in/out) avec les interfaces et les délégués » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon C# Academy ?

Oui. Chaque leçon C# Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Méthodes et types génériques ; contraintes
  2. Variance (in/out) avec les interfaces et les délégués
  3. Types de références nullables (sensibilisation) et annotations (modèles C# 6)
← Retour à C# Academy