6
votes

IList et liste conversions avec interfaces

Je comprends généralement les interfaces, l'héritage et le polymorphisme, mais une chose m'a perplexe.

Dans cet exemple, Cat Implements Ianimal et bien sûr implémente ilist : xxx

mais il génère une erreur de compilation (ne peut pas convertir implicitement le type ...) . Cela ne fonctionnera pas non plus si j'utilise une superclasse d'As fusque [animal] que le chat hérite de. Cependant, si je remplace ianimal avec chat : xxx

il compile bien.

in mon esprit, parce que chat implémente ianimal , le premier exemple devrait être acceptable, ce qui nous permet de renvoyer une interface pour la liste et le type contenu .

Quelqu'un peut-il expliquer pourquoi ce n'est pas valide? Je suis sûr qu'il y a une explication logique.


0 commentaires

6 Réponses :


1
votes

Ce type de Covariance n'est pas pris en charge en C # 4.0. Il est raisonnable d'attendre le comportement que vous voulez, il n'est tout simplement pas pris en charge (pour l'instant).


2 commentaires

Pouvez-vous clarifier? Covariance et Contravariance sont soutenus dans C # 4.0, mais ilist n'est pas une interface covariante.


Haha, eh bien, Eric Lippert vient de répondre, alors je pense que cela en résume: D



1
votes

Vous pouvez atteindre cela à l'aide de LINQ:

IList<IAnimal> cats = new List<Cat>().Cast<IAnimal>();


0 commentaires

6
votes

c # ne prend pas en charge ce type de variance sur ilist pour des raisons de sécurité de type-sécurité.

Si C # a soutenu cela, que vous attendriez-vous ici? xxx

en C # 4 Vous pouvez faire quelque chose comme ceci: xxx

ceci est parce que le ienumerable < T> interface prend en charge la variance de ce type. Un ienumerable est une séquence en lecture seule, il n'ya donc aucun moyen de pouvoir ajouter ultérieurement un chien ou un écureuil sur un < Code> IEnumerable c'est en fait une liste de chat .


0 commentaires

20
votes

Il y a une explication logique, et cette question exacte est posée à peu près tous les jours sur Stackoverflow.

Supposons que c'était légal: P>

IEnumerable<IAnimal> cats = new List<Cat>(); 


3 commentaires

Merci Eric. Je vais certainement lire vos articles. Toutes mes excuses de poser une question continuellement répétée ... feront une recherche bien meilleure recherche la prochaine fois.


@Mark: De rien, et pas de soucis; Le fait que cette question soit posée autant est l'une des choses qui ont motivé l'ajout de la fonctionnalité au C # 4 en premier lieu. Il est clair que les gens ont une intuition que la variance générique devrait faire partie du système de type. Maintenant, il s'agit simplement d'éduquer les gens sur quels types de variance sont prudemment sûrs.


Une mise à jour. J'ai maintenant lu des articles d'Eric et ils éclairent parfaitement la covariance de la covariance. Je lis également la section à ce sujet en C # en profondeur par Jon Skeet, qui fournit un bon résumé aussi (et des tactiques pour faire face à la covariance et à la contrevenance). Quelqu'un d'autre qui luttant avec le concept ne devrait pas ne chercher plus loin que ces deux ressources à mon avis. Merci à tous ceux qui ont offert des conseils.



1
votes

IList n'est pas une interface covariante (ou ce serait ilist ). C'est parce que IList prend les deux type T comme paramètre et le renvoie comme une valeur de retour des méthodes, ce qui rend la problématique de la covariance.

Par exemple, si dans votre exemple:

ilist chats = nouvelle liste ();

Vous vouliez ajouter un nouveau chat, des chats, cela permettrait:

chats.add (nouveau chien ());

supposer que le chien a également mis en œuvre Ianimal, c'est évidemment incorrect et ne fonctionnerait pas. C'est pourquoi il n'est pas une interface covariante ou contrevenariant.


0 commentaires

0
votes

Si vous avez besoin de covariance et de cravarariance sur une interface de liste, vous devez définir une interface IREADRABLELIST et IWRITBLLIST , et dériver un type de liste qui implémente à la fois lecturablisant . Cela permettrait alors de passer une nouvelle liste à une routine qui attend un lecteur ou un writablelist .


0 commentaires