Question

Tout hérite de l'objet. C'est la base de l'héritage. Tout peut être implicitement lancé dans l’arbre de l’héritage, c’est-à-dire.

object me = new Person();

Par conséquent, jusqu'à sa conclusion logique, un groupe de personnes serait également un groupe d'objets:

List<Person> people = new List<Person>();
people.Add(me);
people.Add(you);
List<object> things = people; // Ooops.

Sauf que cela ne fonctionnera pas, les concepteurs de .NET ont soit négligé cela, soit il y a une raison, et je ne sais pas trop laquelle. Au moins une fois que je me suis retrouvé dans une situation où cela aurait été utile, mais je devais finir par utiliser un bidouillage désagréable (liste de sous-classes juste pour implémenter un opérateur de casting).

La question est la suivante: y at-il une raison à ce comportement? Existe-t-il une solution plus simple pour obtenir le comportement souhaité?

Pour mémoire, je pense que la situation dans laquelle je voulais ce type de comportement était une fonction d'impression générique qui affichait des listes d'objets en appelant ToString () et en formatant correctement les chaînes.

Était-ce utile?

La solution

Bien, tous ceux qui ont utilisé des génériques dans .net ont dû le rencontrer à un moment ou à un autre.

Oui, intuitivement, cela devrait fonctionner. Non, dans la version actuelle du compilateur C #, ce n'est pas le cas.

Eric Lippert a une très bonne explication de ce problème (il se divise en onze parties ou quelque chose comme ça et vous dérangera l'esprit par endroit, mais ça vaut la peine d'être lu). Voir ici .

modifier:

a creusé un autre lien pertinent, celui-ci explique comment java gère cela. Voir ici

.

Autres conseils

vous pouvez utiliser linq pour le lancer:

IEnumerable<Person> oldList = someIenumarable;
IEnumerable<object> newList = oldlist.Cast<object>()

À première vue, cela n’a pas de sens intuitif. Mais c'est le cas. Regardez ce code:

List<Person> people = new List<Person>();
List<object> things = people; // this is not allowed
// ...
Mouse gerald = new Mouse();
things.add(gerald);

Nous avons soudainement une liste d'objets Personne ... avec une souris à l'intérieur!

Ceci explique pourquoi l'affectation d'un objet de type A < T > à une variable de type A < S > n'est pas autorisée, même si S est un supertype de T .

La solution de contournement de linq est bonne. Une autre solution de contournement, puisque vous utilisez un objet type, consiste à transmettre la liste sous la forme IEnumerable (et non la version générique).

Modifier : C # 4 (actuellement en version bêta) prend en charge un paramètre de type covariant dans IEnumerable. Bien que vous ne puissiez pas attribuer directement à une liste < objet > ;, vous pouvez transmettre votre liste à une méthode qui attend un IEnumerable < objet >.

Bien que ce que vous tentiez de faire soit vraiment logique, il s’agit en fait d’une fonctionnalité que beaucoup de langues ne prennent pas en charge de manière native. C'est ce qu'on appelle co / contra variance, qui consiste à déterminer quand et comment les objets peuvent être implicitement convertis d'une chose à une autre par un compilateur. Heureusement, le C # 4.0 apportera covariance et contravariance à l’arène C #, et de tels lancers implicites comme celui-ci devraient être possibles.

Pour une explication détaillée à ce sujet, la vidéo Channel9 suivante pourrait être utile:

http://channel9.msdn.com/shows/Going+Deep/Inside-C-40-dynamic-type-optional-parameters-more-COM-friendly/

Avec les méthodes d'extension linq, vous pouvez faire

IEnumerable<object> things = people.Cast<object>();
List<object> things = people.Cast<object>().ToList();

Sinon, puisque vous tapez fortement dans la liste, la conversion implicite n'est pas autorisée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top