Undersøg variansen i stedfortrædere
Varians i C# giver dig mulighed for at bruge mere fleksible metodesignaturer sammen med stedfortrædere. Den giver dig mulighed for at tildele metoder til stedfortrædere, selvom deres parametertyper eller returtyper ikke er nøjagtigt de samme, så længe de følger visse regler. Varians er nyttig, når du arbejder med nedarvningshierarkier.
Hvad er varians?
Varians er et begreb i C#, der giver dig mulighed for at bruge en mere afledt type end den, der er angivet i en stedfortræder eller grænseflade. Det giver dig mulighed for at oprette mere fleksibel kode, der kan genbruges, ved at tillade, at metoder tildeles til stedfortrædere, selvom deres signaturer ikke stemmer nøjagtigt overens.
Der er to typer varians:
- Kovarians: Gør det muligt for en metode at have en returtype, der er mere afledt end den type, der er defineret i stedfortræderen.
- Contravariance: Gør det muligt for en metode at acceptere parametre, der er mindre afledt end parametrene i stedfortrædertypen.
Understøttelse af varians omfatter generiske og ikke-generiske stedfortrædere.
Afvigelse i forhold til brugerdefinerede stedfortrædere
Brugerdefinerede stedfortrædere er brugerdefinerede stedfortrædertyper. Variansen kan anvendes på brugerdefinerede stedfortrædere for at gøre dem mere fleksible.
I følgende eksempel vises det, hvordan du bruger varians med brugerdefinerede stedfortrædere:
public class Animal { }
public class Dog : Animal { }
// Define a delegate that takes a Dog and returns an Animal
public delegate Animal AnimalDelegate(Dog dog);
// Method that matches the delegate signature
public static Animal GetAnimal(Dog dog) => new Animal();
// Method that uses covariance (returns a more derived type)
public static Dog GetDog(Dog dog) => new Dog();
// Method that uses contravariance (accepts a less derived type)
public static Animal GetAnimalFromAnimal(Animal animal) => new Animal();
public class Program
{
public static void Main()
{
AnimalDelegate del;
// Assign method with matching signature
del = GetAnimal;
Animal animal = del(new Dog());
// Assign method with covariant return type
del = GetDog;
animal = del(new Dog());
// Assign method with contravariant parameter type
del = GetAnimalFromAnimal;
animal = del(new Dog());
}
}
I dette eksempel kan tildeles til GetDog , AnimalDelegate fordi Dog er en mere afledt type end Animal (kovarians). På samme måde kan tildeles, GetAnimalFromAnimal fordi Animal er en mindre afledt type end Dog (contravariance).
Afvigelse i forhold til stedfortrædere, der er skrevet meget
Varians gælder også for stedfortrædere, der er skrevet meget, f.eks Action . og Func.
Kovarians med Func
I følgende eksempel vises kovarians med Func:
public class Person { }
public class Employee : Person { }
public static Employee FindEmployee(string title) => new Employee();
public class Program
{
public static void Main()
{
// Func<string, Person> can hold a method that returns Employee
Func<string, Person> func = FindEmployee;
Person person = func("Manager");
}
}
I dette eksempel FindEmployee returnerer en Employee, som er mere afledt end Person, så den kan tildeles til Func<string, Person>.
Contravariance med Action
I følgende eksempel vises contravariance med Action:
public class Animal { }
public class Dog : Animal { }
public static void HandleAnimal(Animal animal) { }
public class Program
{
public static void Main()
{
// Action<Dog> can hold a method that takes Animal
Action<Dog> action = HandleAnimal;
action(new Dog());
}
}
HandleAnimal Her accepterer Animal, som er mindre afledt end Dog, så den kan tildeles til Action<Dog>.
Varians i generiske produkter
Variansen kan også anvendes på generiske typeparametre ved hjælp af nøgleordene in og out .
Covariant generisk type
Nøgleordet out bruges til at deklarere en covariant generisk typeparameter. Denne funktion giver dig mulighed for at bruge en mere afledt type som returtype.
I følgende eksempel vises kovarians i generiske udtryk:
public interface ICovariant<out T> { T Get(); }
public class Animal { }
public class Dog : Animal { }
public class CovariantExample : ICovariant<Dog>
{
public Dog Get() => new Dog();
}
public class Program
{
public static void Main()
{
ICovariant<Animal> covariant = new CovariantExample();
Animal animal = covariant.Get();
}
}
I dette eksempel kan du ICovariant<out T> tildele til , ICovariant<Dog> fordi ICovariant<Animal> er mere afledt end DogAnimal .
Contravariant generisk type
Nøgleordet in bruges til at deklarere en contravariant generisk typeparameter. Denne funktion giver dig mulighed for at bruge en mindre afledt type som parametertype.
I følgende eksempel vises contravariance i generiske produkter:
public interface IContravariant<in T> { void Set(T value); }
public class Animal { }
public class Dog : Animal { }
public class ContravariantExample : IContravariant<Animal>
{
public void Set(Animal value) { }
}
public class Program
{
public static void Main()
{
IContravariant<Dog> contravariant = new ContravariantExample();
contravariant.Set(new Dog());
}
}
Her kan tildeles IContravariant<in T> til IContravariant<Animal> , IContravariant<Dog> fordi Animal er mindre afledt end Dog.
Nøglepunkter
- Varians giver dig mulighed for at bruge mere fleksible metodesignaturer sammen med stedfortrædere.
- Kovarians gør det muligt for en metode at have en returtype, der er mere afledt end den type, der er defineret i stedfortræderen.
- Contravariance gør det muligt for en metode at acceptere parametre, der er mindre afledt end parametrene i stedfortrædertypen.
- Brugerdefinerede og stærkt indtastede stedfortrædere kan bruge varians til at være mere fleksible.
- Generiske produkter kan bruge variansen med nøgleordene
inogouttil at deklarere generiske typeparametre for kontravariant og covariant.