Je n'ai pas assisté à PDC 2008, mais j'ai entendu des nouvelles selon lesquelles C # 4.0 est annoncé pour prendre en charge la covariance et la contra-variance génériques. Autrement dit, List<string>
peut être attribué à List<object>
. Comment cela pourrait-il être?
Dans le livre C # in Depth de Jon Skeet , 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 apporterait-il le chaos?
Quelqu'un connaît les détails sur C # 4.0 peut donner quelques explications?
c#
c#-4.0
covariance
contravariance
generic-variance
Morgan Cheng
la source
la source
Réponses:
La variance ne sera prise en charge que de 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 pour essayer d'utiliser un
List<Banana>
comme unList<Fruit>
(ou quoi que ce soit) ne fonctionneront toujours pas - mais quelques autres scénarios le seront.Premièrement, il ne sera pris en charge que pour les interfaces et les délégués.
Deuxièmement, il faut que l'auteur de l'interface / du délégué décore les paramètres de type comme
in
(pour contravariance) ouout
(pour covariance). L'exemple le plus évident est celuiIEnumerable<T>
qui ne vous permet que d'en "retirer" des valeurs - cela ne vous permet pas d'en ajouter de nouvelles. Cela deviendraIEnumerable<out T>
. Cela ne nuit pas du tout à la sécurité des types, mais vous permet de renvoyer un àIEnumerable<string>
partir d'une méthode déclarée à renvoyerIEnumerable<object>
par exemple.La contravariance est plus difficile à donner des exemples concrets d'utilisation d'interfaces, mais c'est facile avec un délégué. Considérez
Action<T>
- cela représente juste une méthode qui prend unT
paramètre. Ce serait bien de pouvoir convertir de manière transparente en utilisant unAction<object>
commeAction<string>
- toute méthode qui prend unobject
paramètre fonctionnera bien lorsqu'elle sera présentée avec un à lastring
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 plutôt une conversion de référence.)J'espère que cela clarifie un peu les choses - s'il vous plaît laissez-moi savoir si cela n'a pas de sens!
la source
List<Banana>
comme unIList<Fruit>
"comme @ Ark-kun l'a dit? Si tel est le cas, comment est-ce possible, bien que le paramètre de type de l'IList<T>
interface ne soit pas défini comme covariant (nonout T
, mais simplementT
).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=3MQDrKbzvqU
https://www.youtube.com/watch?v=XRIadQaBYlI
https://www.youtube.com/watch?v=St9d2EDZfrg
la source