D'abord, j'ai lu beaucoup d'explications sur DONC et les blogs sur la covariance et la contravariance et un merci à Eric Lippert pour produire de telles une grande série sur la Covariance et la Contravariance.
Toutefois, j'ai une question plus précise que je suis en train d'essayer d'obtenir ma tête autour de un peu.
Autant je comprends par Eric explication est que la Covariance et la Contravariance sont les deux adjectifs qui décrivent une transformation. Covariante de transformation est celle qui conserve l'ordre des types et Contravariant de la transformation est l'un que l'inverse.
Je comprends la covariance de telle manière que je pense que la plupart des développeurs de comprendre intuitivement.
//covariant operation
Animal someAnimal = new Giraffe();
//assume returns Mammal, also covariant operation
someAnimal = Mammal.GetSomeMammal();
L'opération de retour ici est covariant que nous sommes en préservant la taille à laquelle les deux Animaux est encore plus grand que les Mammifères ou la Girafe. Sur cette note, la plupart des opérations de retour sont covariants, contravariant opérations n'aurait aucun sens.
//if return operations were contravariant
//the following would be illegal
//as Mammal would need to be stored in something
//equal to or less derived than Mammal
//which would mean that Animal is now less than or equal than Mammal
//therefore reversing the relationship
Animal someAnimal = Mammal.GetSomeMammal();
Ce morceau de code n'aurait pas de sens pour la plupart des développeurs.
Ma confusion réside dans Contravariant argument paramètres. Si vous aviez une méthode telle que
bool Compare(Mammal mammal1, Mammal mammal2);
J'ai toujours appris que les paramètres d'entrée toujours la force contravariant comportement. De sorte que si le type est utilisé comme paramètre d'entrée son comportement doit être contravariant.
Cependant quelle est la différence entre le code suivant
Mammal mammal1 = new Giraffe(); //covariant
Mammal mammal2 = new Dolphin(); //covariant
Compare(mammal1, mammal2); //covariant or contravariant?
//or
Compare(new Giraffe(), new Dolphin()); //covariant or contravariant?
De la même manière que vous ne pouvez pas faire quelque chose comme cela, vous ne pouvez pas le faire
//not valid
Mammal mammal1 = new Animal();
//not valid
Compare(new Animal(), new Dolphin());
Je suppose que ce que je demande est, ce qui fait un argument de méthode passage d'un contravariant de la transformation.
Désolé pour le long post, je suis peut-être comprendre ce tort.
EDIT:
Par une conversation ci-dessous, je comprends que, par exemple à l'aide d'un délégué de la couche peut clairement montrer la contravariance. Considérons l'exemple suivant
//legal, covariance
Mammal someMammal = new Mammal();
Animal someAnimal = someMammal;
// legal in C# 4.0, covariance (because defined in Interface)
IEnumerable<Mammal> mammalList = Enumerable.Empty<Mammal>();
IEnumerable<Animal> animalList = mammalList;
//because of this, one would assume
//that the following line is legal as well
void ProcessMammal(Mammal someMammal);
Action<Mammal> processMethod = ProcessMammal;
Action<Animal> someAction = processMethod;
Bien sûr que c'est illégal parce que quelqu'un peut passer n'importe quel Animal à uneaction, où, comme le ProcessMammal attend quoi c'est de Mammifères ou plus spécifique ( à moins que l'un Mammifère ). C'est pourquoi uneaction doit seulement être une Action ou quelque chose de plus spécifique (Action)
Cependant, c'est l'introduction d'une couche de délégués dans le milieu, est-il nécessaire que pour une contravariant de projection à arriver, il y a un délégué dans le milieu? Et si nous devions définir comme une interface de nous déclarer le paramètre argument comme un contravariant type seulement parce que nous ne voulons pas de quelqu'un pour être en mesure de faire ce que j'avais indiqué ci-dessus avec les délégués?
public interface IProcess<out T>
{
void Process(T val);
}