Qualcuno potrebbe fornirmi semplici esempi C# di convalescenza, controvarianza, invarianza e contro-invarianza (se tale cosa esiste).
Non ho idea di cosa significa "contro-invarianza". Il resto è facile.
Ecco un esempio di covarianza:
void FeedTheAnimals(IEnumerable<Animal> animals)
{
foreach(Animal animal in animals)
animal.Feed();
}
...
List<Giraffe> giraffes = ...;
FeedTheAnimals(giraffes);
L'interfaccia è IEnumerable<T>
covariante. Il fatto che la giraffa è convertibile in animali implica che IEnumerable<Giraffe>
è convertibile in IEnumerable<Animal>
. Dal momento che List<Giraffe>
implementa IEnumerable<Giraffe>
questo codice riesce a C# 4; sarebbe fallito in C# 3 perché la covarianza su IEnumerable<T>
non funzionava in C# 3.
Questo dovrebbe avere senso. Una sequenza di giraffe può essere trattata come una sequenza di animali.
Ecco un esempio di controvarianza:
void DoSomethingToAFrog(Action<Frog> action, Frog frog)
{
action(frog);
}
...
Action<Animal> feed = animal=>{animal.Feed();}
DoSomethingToAFrog(feed, new Frog());
Il Action<T>
delegato è controvariante. Il fatto che la rana è convertibile in animali implica che Action<Animal>
è convertibile in Action<Frog>
. Si noti come questo rapporto è il direzione opposta della covariante uno; è per questo che è una variante "contro". A causa della convertibilità, questo codice ha successo; sarebbe fallito in C# 3.
Questo dovrebbe avere un senso. L'azione può prendere qualsiasi animale; abbiamo bisogno di un'azione che possa prendere qualsiasi Rana, e un'azione che può prendere qualsiasi Animale sicuramente può anche prendere qualsiasi Rana.
Un esempio di invarianza:
void ReadAndWrite(IList<Mammal> mammals)
{
Mammal mammal = mammals[0];
mammals[0] = new Tiger();
}
Possiamo passare un IList<Giraffe>
a questa cosa? No, perché qualcuno sta per scrivere una Tigre e una Tigre non può essere in una lista di Giraffe. Possiamo passare un IList<Animal>
in questa cosa? No, perché leggiamo un Mammifero e una lista di Animali potrebbe contenere una Rana. IList<T>
è invariante. Può essere usato solo per quello che è in realtà.
Per alcune considerazioni aggiuntive sul design di questa funzione, vedere la mia serie di articoli su come l'abbiamo progettata e costruita.
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/
qualcuno ha dato gettando un oggetto a 'System.Object' come un esempio di covarianza? Non è nemmeno giusto. –
L'ho preso per indicare il passaggio di qualche tipo di oggetto (con un tipo specifico, più derivato) al posto di 'System.Object', non necessariamente il cast di' object' su 'System.Object', che sarebbe inutile. –
_Variance_ non deve essere confuso con _casting_, non sono la stessa cosa. Vedi: [Differenza tra covarianza e upcasting] (http://stackoverflow.com/a/6707697/949681). – Pressacco