web-dev-qa-db-fra.com

Comment la covariance et la contravariance génériques sont-elles implémentées dans C # 4.0?

Je n'ai pas assisté à PDC 2008, mais j'ai entendu des nouvelles que C # 4.0 est annoncé pour prendre en charge la covariance et la contre-variance génériques. C'est-à-dire, List<string> peut être affecté à List<object>. Comment cela pourrait-il être?

Dans le livre de Jon Skeet C # en profondeur , il est expliqué pourquoi les génériques C # ne prennent pas en charge la covariance et la contre-variance. C'est principalement pour écrire du code sécurisé. Maintenant, C # 4.0 a changé pour les prendre en charge. Cela amènerait-il le chaos?

Quelqu'un sait que les détails sur C # 4.0 peuvent donner une explication?

106
Morgan Cheng

La variance ne sera prise en charge que d'une manière sûre - en fait, en utilisant les capacités que le CLR possède déjà. Ainsi, les exemples que je donne dans le livre d'essayer d'utiliser un List<Banana> comme un List<Fruit> (ou quoi que ce soit) ne fonctionnera toujours pas - mais quelques autres scénarios le feront.

Premièrement, il ne sera pris en charge que pour les interfaces et les délégués.

Deuxièmement, il requiert que l'auteur de l'interface/délégué décore les paramètres de type comme in (pour la contravariance) ou out (pour la covariance). L'exemple le plus évident est IEnumerable<T> qui ne vous permet que d'en retirer "des valeurs" - il ne vous permet pas d'en ajouter de nouvelles. Cela deviendra IEnumerable<out T>. Cela ne nuit pas du tout à la sécurité du type, mais vous permet de renvoyer un IEnumerable<string> à partir d'une méthode déclarée renvoyer IEnumerable<object> par exemple.

Il est plus difficile de donner des exemples concrets d'utilisation d'interfaces, mais c'est facile avec un délégué. Considérer Action<T> - qui représente simplement une méthode qui prend un paramètre T. Ce serait bien de pouvoir convertir de façon transparente en utilisant un Action<object> en tant que Action<string> - toute méthode qui prend un paramètre object ira bien quand elle sera présentée avec un string à la place. Bien sûr, C # 2 a déjà une covariance et une contravariance des délégués dans une certaine mesure, mais via une conversion réelle d'un type de délégué à un autre (création d'une nouvelle instance) - voir P141-144 pour des exemples. C # 4 rendra cela plus générique et (je crois) évitera de créer une nouvelle instance pour la conversion. (Ce sera une conversion de référence à la place.)

J'espère que cela clarifiera un peu les choses - faites-le moi savoir si cela n'a pas de sens!

155
Jon Skeet

Non pas que Jon ne l'ait pas déjà couvert, mais voici quelques liens vers des blogs et des vidéos d'Eric Lippert. Il fait un bon travail pour l'expliquer avec des exemples.

https://blogs.msdn.Microsoft.com/ericlippert/2007/10/16/covariance-and-contravariance-in-c-part-one/

Les vidéos:

https://www.youtube.com/watch?v=3MQDrKbzvq

https://www.youtube.com/watch?v=XRIadQaBYlI

https://www.youtube.com/watch?v=St9d2EDZfrg

5
kemiller2002