60 votes

Différence entre covariance et upcasting

Quelle est la différence entre la covariance et l'upcasting, ou, plus précisément, pourquoi sont-ils donné des noms différents?

J'ai vu l'exemple suivant, dénommé "upcasting':

string s = "hello";
object o = s;  //upcast to 'string' to 'object'

Attendu que le suivant, j'ai vu appelée "la covariance':

string[] s = new string[100];
object[] o = s;

IEnumerable<string> ies = new List<string>();
IEnumerable<object> ieo = ies;

Maintenant, à mon œil non averti, la covariance semble être le même que upcasting, sauf qu'il se réfère à la coulée des collections. (Et d'une déclaration similaire peut être faite concernant la contravariance et de passer).

Est-ce vraiment si simple?

57voto

Jason Points 125291

Maintenant, à mon œil non averti, la covariance semble être le même que upcasting, sauf qu'il se réfère à la coulée des collections. (Et d'une déclaration similaire peut être faite concernant la contravariance et de passer).

Est-ce vraiment si simple?

La Covariance n'est pas sur l'upcasting, même si je peux voir pourquoi vous pensez que c'est lié.

La Covariance sur les éléments suivants idée très simple. Disons que vous avez une variable derivedSequence de type IEnumerable<Derived>. Disons que vous avez une variable baseSequence de type IEnumerable<Base>. Ici, Derived provient Base. Puis, avec la covariance, ce qui suit est une mission légale, et une référence implicite conversion se produit:

baseSequence = derivedSequence;

Notez que ce n'est pas upcasting. Il n'est pas le cas qu' IEnumerable<Derived> provient IEnumerable<Base>. C'est plutôt la covariance qui vous permet d'affecter la valeur de la variable derivedSequence à la variable baseSequence. L'idée est que les variables de type Base peut être attribuée à partir d'objets de type Derived, et depuis IEnumerable<T> est covariant dans son paramètre, les objets de type IEnumerable<Derived> peuvent être attribués à des variables de type IEnumerable<Base>.

Bien sûr, je n'ai pas encore vraiment expliqué ce que covariance. En général, la covariance sur les éléments suivants idée simple. Disons que vous avez un mappage F de types de types (je vais désigner cette cartographie en F<T>; étant donné un type T de son image dans le mappage F est F<T>.) Disons que cette cartographie a la suite de très spécial de la propriété:

si X est d'affectation compatible avec Y, alors F<X> est d'affectation compatible avec F<Y> .

Dans ce cas, nous disons que l' F est covariant dans son paramètre T. (Ici, de dire que "A est d'affectation compatible avec B" où A et B sont des types référence signifie que les instances de l' B peuvent être stockées dans des variables de type A.)

Dans notre cas, IEnumerable<T> en C# 4.0, une référence implicite de conversion à partir des instances de l' IEnumerable<Derived> de IEnumerable<Base> si Derived est dérivé de l' Base. La direction de la compatibilité d'affectation est préservée, et c'est pourquoi nous disons qu' IEnumerable<T> est covariant dans son paramètre de type.

19voto

Jon Points 194296

Casting fait référence à la modification du type statique d' objets et d'expressions .

La variance fait référence à l' interchangeabilité ou à l'équivalence des types dans certaines situations (telles que les paramètres, les génériques et les types de retour).

15voto

antlersoft Points 10046

IEnumerable<string> n'est pas dérivé de IEnumerable<object> , de sorte que la distribution entre eux n'est pas une conversion ascendante. IEnumerable est covariant dans son paramètre de type et la chaîne est dérivée de object. La conversion est donc autorisée.

7voto

La raison pour laquelle ils sont deux concepts différents, c'est que, contrairement à l'upcasting, la covariance n'est pas toujours autorisé. Il aurait été facile pour les concepteurs du type de système pour faire IList<Cat> être considérés comme des "dérivés" de IList<Animal>, mais ensuite, nous nous heurtons à des problèmes:

IList<Cat> cats = new List<Cat>();
IList<Animal> animals = cats; 
animals.Add(new Dog()); //Uh oh!

Si cela était permis, maintenant, notre cats liste contient un Dog!

En revanche, l' IEnumerable<T> interface n'a aucun moyen d'ajouter des éléments, c'est donc parfaitement valide (C# 4.0):

IList<Cat> cats = new List<Cat>();
IEnumerable<Animal> animals = cats;
//There's no way to add things to an IEnumerable<Animal>, so here we are ok

1voto

Jon Egerton Points 16192

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X