mógłby ktoś podać mi proste C# przykłady convariance, kontrawariancji, niezmienności i przeciwwskazania niezmienności (jeśli coś takiego istnieje).
Nie mam pojęcia, co oznacza "przeciw-niezmienniczość". Reszta jest łatwa.
Oto przykład kowariancji:
void FeedTheAnimals(IEnumerable<Animal> animals)
{
foreach(Animal animal in animals)
animal.Feed();
}
...
List<Giraffe> giraffes = ...;
FeedTheAnimals(giraffes);
Interfejs IEnumerable<T>
jest kowariantna. Fakt, że Giraffe można zamienić na Animal, oznacza, że IEnumerable<Giraffe>
można zamienić na IEnumerable<Animal>
. Od List<Giraffe>
implementuje IEnumerable<Giraffe>
ten kod kończy się pomyślnie w C# 4; nie powiodłoby się w C# 3, ponieważ kowariancja na IEnumerable<T>
nie działała w C# 3.
To powinno mieć sens. Ciąg żyraf może być traktowany jako sekwencja zwierząt.
Oto przykład z kontrawariancji:
void DoSomethingToAFrog(Action<Frog> action, Frog frog)
{
action(frog);
}
...
Action<Animal> feed = animal=>{animal.Feed();}
DoSomethingToAFrog(feed, new Frog());
Action<T>
delegat jest kontrawariantny. Fakt, że Frog można zamienić na Animal, oznacza, że Action<Animal>
można zamienić na Action<Frog>
. Zauważ, jak ta relacja jest przeciwna w kierunku kowariantnego; dlatego jest to wariant "contra". Z powodu wymienialności ten kod się powiódł; to by się nie udało w C# 3.
To powinno mieć sens. Akcja może przyjąć dowolne Zwierzę; potrzebujemy akcji, która może przyjąć dowolną Żabę, a akcja, która może przyjąć każde Zwierzę, z pewnością może wziąć dowolną Żabę.
Przykładem niezmienności:
void ReadAndWrite(IList<Mammal> mammals)
{
Mammal mammal = mammals[0];
mammals[0] = new Tiger();
}
możemy zdać IList<Giraffe>
do tej rzeczy? Nie, ponieważ ktoś ma zamiar napisać do niego Tygrysa, a tygrys nie może być na liście żyraf. Czy możemy przekazać w tej sprawie IList<Animal>
? Nie, ponieważ będziemy czytać z tego Ssaka, a lista Zwierząt może zawierać Żabę. IList<T>
jest niezmienna. Można go używać tylko tak, jak jest w rzeczywistości.
Aby uzyskać dodatkowe informacje na temat projektu tej funkcji, zapoznaj się z moją serią artykułów na temat tego, jak ją zaprojektowaliśmy i zbudowaliśmy.
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/
Ktoś dał oddające obiekt do 'System.Object' jako przykład kowariancji? To wcale nie jest w porządku. –
Uznałem, że to oznacza przekazanie jakiegoś obiektu (z konkretnym, bardziej wyprowadzonym typem) w miejsce 'System.Object', niekoniecznie rzutując' object' na 'System.Object', co byłoby bezcelowe. –
_Variance_ nie należy mylić z _casting_, to nie to samo. Zobacz: [Różnica między kowariancją a upcastingiem] (http://stackoverflow.com/a/6707697/949681). – Pressacco