En C#, pourquoi pas une Liste<string> object être stockés dans une Liste<object> variable
Il semble que l'un des objets de la Liste ne peuvent pas être stockés dans une Liste de variables en C#, et ne peut même pas être explicitement exprimés de cette façon.
List<string> sl = new List<string>();
List<object> ol;
ol = sl;
résultats est Impossible de convertir implicitement le type System.Collections.Generic.List<string>
à System.Collections.Generic.List<object>
Et puis...
List<string> sl = new List<string>();
List<object> ol;
ol = (List<object>)sl;
résultats Ne peut pas convertir le type de System.Collections.Generic.List<string>
à System.Collections.Generic.List<object>
Bien sûr, vous pouvez le faire en tirant sur tout ce qui sort de la liste de chaînes et de le remettre dans un à la fois, mais c'est plutôt alambiqué solution.
- Ça va changer avec C# 4.0, de sorte que vous pourriez voulez de recherche de la covariance et la contravariance. Il permettra à de telles choses dans un type de manière sécuritaire.
- Plus ou moins double: stackoverflow.com/questions/317335/...
- Jean - > C#4 ne le permettrons pas. Penser à l'ol.Add(new object());
- Il est répondu par Jon Skeet ici: stackoverflow.com/a/2033921/1070906
Vous devez vous connecter pour publier un commentaire.
Pensez-y de cette façon, si vous décidez de faire un tel casting, puis ajouter un objet de type Foo à la liste, la liste des chaînes est plus cohérent. Si vous deviez effectuer une itération de la première référence, vous obtenez une classe cast exception, car une fois que vous frappez les Foo exemple, les Foo n'a pas pu être converti en string!
Comme une note de côté, je pense qu'il serait plus important de savoir si vous pouvez ou non faire l'inverse cast:
Je n'ai pas utilisé le langage C# dans un certain temps, donc je ne sais pas si c'est légal, mais ce genre de cast est en fait (peut-être) utile. Dans ce cas, vous allez partir d'une classe plus générale (objet) à une classe plus spécifique (string) qui s'étend à partir de la générale. De cette façon, si vous ajouter à la liste de chaînes, vous ne violez pas la liste d'objets.
Quelqu'un sait ou peut tester si un tel casting est légal en C#?
ol
avait en elle quelque chose qui n'est pas une chaîne, je pense que je peux attendre la fonte à l'échec lors de l'exécution. Mais où vous avez vraiment un problème si le casting réussi, et puis quelque chose ont été ajoutés àol
ce n'est pas une chaîne. Parce quesl
référence au même objet, maintenant, votreList<string>
contenant une chaîne non. LeAdd
est le problème, qui je suppose, justifie pourquoi ce code ne compile pas, mais il va compiler si vous modifiezList<object> ol
àIEnumerable<object> ol
, qui n'a pas d'Add
. (J'ai vérifié dans C# 4.)InvalidCastException
parce que le runtime type deol
est encoreList<object>
.Si vous êtes en utilisant .NET 3.5 ont un look à la Énumérable.Fonte de la méthode. C'est une méthode d'extension de sorte que vous pouvez l'appeler directement sur la Liste.
Ce n'est pas exactement ce que vous avez demandé, mais devrait faire l'affaire.
Edit: Comme l'a noté Zooba, vous pouvez appeler l'ol.ToList() pour obtenir une Liste
Vous ne pouvez pas convertir entre les types génériques avec différents paramètres de type. Spécialisé types génériques ne font pas partie de la même arborescence d'héritage et sont donc sans rapport avec les types.
Pour ce faire pré-NET 3.5:
À L'Aide De Linq:
La raison en est qu'une classe générique comme
List<>
est, pour la plupart des fins, traités à l'extérieur comme une classe normale. par exemple, quand vous ditesList<string>()
le compilateur ditListString()
(qui contient des chaînes de caractères). [Technique folk: c'est un très plaine-anglais-identifiés version de ce qui se passe]Par conséquent, évidemment, le compilateur ne peut pas être assez intelligent pour convertir un ListString à un ListObject par la coulée des éléments de sa collection.
C'est pourquoi il existe des méthodes d'extension pour IEnumerable comme Convertir() qui permettent de faciliter l'approvisionnement de conversion pour les éléments stockés à l'intérieur d'une collection, qui pourrait être aussi simple que de la conversion de l'un à l'autre.
Cela a beaucoup à voir avec la covariance, par exemple, les types génériques sont considérés comme des paramètres, et si les paramètres ne permettent pas de résoudre correctement un plus spécifique alors que l'opération échoue. L'implication est que vous avez vraiment ne peut pas lancer d'un type plus général comme objet. Et comme l'a déclaré Rex, l'objet de la Liste ne sera pas converti chaque objet pour vous.
Vous pourriez vouloir essayer le ff code à la place:
ou:
ol sera (théoriquement) copie de tout le contenu de sl sans problèmes.
Oui, vous pouvez, à partir de .NET 3.5:
Mike - je crois que la contravariance n'est pas autorisé en C# soit
Voir Paramètre de type générique de la variance dans le CLR pour plus d'info.
Je pense que cela (la contravariance) sera effectivement pris en charge en C# 4.0.
http://blogs.msdn.com/charlie/archive/2008/10/27/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx
C'est fait de sorte que vous n'essayez pas de mettre n'importe quel étrange "objet" dans votre "ol" variante de liste (comme
List<object>
semble permettre) - parce que votre code crash alors (parce que la liste est vraimentList<string>
et n'acceptera que les objets de type String). C'est pourquoi vous ne pouvez pas lancer votre variable d'une spécification plus générale.Sur Java c'est l'inverse, vous n'avez pas les génériques, et, au lieu de tout ce qui est de la Liste de l'objet au moment de l'exécution, et vous ne pouvez vraiment des trucs tout objet étrange dans votre soi-disant-strictement Liste tapée. Recherche pour "Réifiée génériques" pour voir une discussion plus large de java problème...
Cette covariance sur les médicaments génériques n'est pas pris en charge, mais vous pouvez réellement le faire avec des tableaux:
C# effectue exécution des vérifications pour vous empêcher de le mettre, disons, un
int
ena
.Voici un autre pre-.NET 3.5 solution pour tout IList dont le contenu peut être exprimés de façon implicite.
(Basé sur Zooba exemple)
J'ai un:
Et j'allais à le remplir avec des données recueillies dans une
List<object>
Ce qui a finalement fonctionné pour moi a été celle-ci:
.Cast
pour le type que vous souhaitez obtenir unIEnumerable
de ce type, alors transtypage de laIEnemuerable
à laList<>
vous le souhaitez.Mm, grâce à des commentaires précédents, j'ai trouvé deux façons de le découvrir. Le premier est l'obtention de la chaîne de liste d'éléments, puis un moulage IEnumerable liste d'objets:
Et la seconde est d'éviter la IEnumerable type d'objet, juste un moulage de la chaîne de type d'objet, puis en utilisant la fonction "toList()" dans la même phrase:
J'aime plus la seconde. J'espère que cette aide.