C# Academy · Lektion

Varians (in/out) med interfaces og delegates

Forstå C#-varians: out til producenter (kovarians) og in til konsumenter (kontravarians) på interfaces og delegates.

Lektion 2 af 38 trin

Varians (in/out) med interfaces og delegates er en gratis C# Academy-lektion på CoddyKit. Dette er lektion 2 af 3. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i C# Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. C# Academy-kurset indeholder 3 lektioner i alt.

Oversigt over varians

Varians gør det muligt for generiske grænseflader og delegater at fungere med nedarvning.

  • out = kovarians (producent)
  • in = kontravarians (forbruger)
  • Det er sikkert, når API'et kun producerer eller kun forbruger T

Demo af kovarians

IEnumerable<out T> er kovariant: en sekvens af katte kan bruges, hvor der forventes en sekvens af dyr.

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);
  }
}

Demo af kontravarians

IComparer<in T> er kontravariant: en sammenligner til Animal fungerer også for Cat, fordi den kun modtager 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);
  }
}

Varians for delegater

Delegater har også varians: Func<out TResult> (producent) og Action<in T> (forbruger).

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());
  }
}

Brugerdefinerede variante grænseflader

Designregel: Markér parametre, der kun bruges som producenter, med out, og parametre, der kun bruges som forbrugere, med in for at aktivere sikre konverteringer.

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());
  }
}

Tips om varians

Tips:

  • out-parametre må kun optræde på outputpositioner (returtyper, kovariante positioner).
  • in-parametre må kun optræde på inputpositioner (metodeparametre).
  • Bland ikke produktion og forbrug af den samme T, når du erklærer varians.
  • Varians gælder for grænseflader og delegater, ikke klasser.

Nøgleordet for kovarians

Hurtigt tjek: Hvilket nøgleord markerer en kovariant typeparameter på en grænseflade eller en delegat?

Opsummering

Opsummering: Brug out til producenter (kovarians) og in til forbrugere (kontravarians) på grænseflader og delegater. Hold API'er ensrettede for at aktivere sikre konverteringer.

Gratis at komme i gang

Lær C# med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
93
Lektioner
346

Ofte stillede spørgsmål

Er lektionen “Varians (in/out) med interfaces og delegates” gratis?

Ja — hele teksten til “Varians (in/out) med interfaces og delegates” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af C# Academy-kurset, skal du opgradere til CoddyKit PRO. C# Academy-kurset indeholder 3 lektioner i alt.

Hvad lærer jeg i “Varians (in/out) med interfaces og delegates”?

Forstå C#-varians: out til producenter (kovarians) og in til konsumenter (kontravarians) på interfaces og delegates. Du øver dig i C# Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på C# Academy?

Der kræves ingen tidligere erfaring. C# Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 3.

Hvor lang tid tager lektionen “Varians (in/out) med interfaces og delegates”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne C# Academy-lektion?

Ja. Alle C# Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Generiske metoder/typer; begrænsninger
  2. Varians (in/out) med interfaces og delegates
  3. Nullable referencetyper (bevidsthed) og annotationer (C# 6-mønstre)
← Tilbage til C# Academy