En C

Il semble qu'un objet List ne puisse pas être stocké dans une variable List en C

请先 登录 后评论

8 réponses

Rex M

La raison en est qu'une classe générique comme List<> est, dans la plupart des cas, traitée en externe comme une classe normale. par exemple. quand vous dites List<string>() le compilateur dit ListString() (qui contient des chaînes). [Technical folks : ceci est une version extrêmement simplifiée en anglais de ce qui se passe]

Par conséquent, il est évident que le compilateur ne peut pas être assez intelligent pour convertir un ListString en un ListObject en transtypant les éléments de sa collection interne.

C'est pourquoi il existe des méthodes d'extension pour IEnumerable comme Convert() qui vous permettent de fournir facilement une conversion pour les éléments stockés dans une collection, ce qui peut être aussi simple que de passer de l'un à l'autre.

请先 登录 后评论
Mike Stone

Pensez-y de cette façon, si vous deviez faire un tel cast, puis ajoutez un objet de type Foo à la liste, la liste des chaînes n'est plus cohérente. Si vous deviez itérer la première référence, vous obtiendriez une exception de cast de classe car une fois que vous avez atteint l'instance de Foo, le Foo ne pourrait pas être converti en chaîne !

En passant, je pense qu'il serait plus important de savoir si vous pouvez ou non faire le casting inversé :

List<object> ol = new List<object>();
List<string> sl;
sl = (List<string>)ol;

Je n'ai pas utilisé C

请先 登录 后评论
Matt Sheppard

Mike - Je crois que la contravariance n'est pas autorisée en C

请先 登录 后评论
Jon Limjap

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 se résolvent pas correctement en un type plus spécifique, l'opération échoue. L'implication de tel est que vous ne pouvez vraiment pas convertir un type plus général comme un objet. Et comme indiqué par Rex, l'objet List ne convertira pas chaque objet pour vous.

Vous voudrez peut-être essayer le code ff à la place :

List<string> sl = new List<string>();
//populate sl
List<object> ol = new List<object>(sl);

ou :

List<object> ol = new List<object>();
ol.AddRange(sl);

ol copiera (théoriquement) tout le contenu de sl sans problème.

请先 登录 后评论
Ray

Si vous utilisez .NET 3.5, jetez un œil à la méthode Enumerable.Cast. C'est une méthode d'extension pour que vous puissiez l'appeler directement sur la liste.

List<string> sl = new List<string>();
IEnumerable<object> ol;
ol = sl.Cast<object>();

Ce n'est pas exactement ce que vous avez demandé, mais devrait faire l'affaire.

Modifier : comme indiqué par Zooba, vous pouvez ensuite appeler ol.ToList() pour obtenir une liste

请先 登录 后评论
Zooba

Vous ne pouvez pas caster entre des types génériques avec des paramètres de type différents. Les types génériques spécialisés ne font pas partie du même arbre d'héritage et sont donc des types non liés.

Pour ce faire avant NET 3.5 :

List<string> sl = new List<string>();
// Add strings to sl

List<object> ol = new List<object>();

foreach(string s in sl)
{
    ol.Add((object)s);  // The cast is performed implicitly even if omitted
}

En utilisant Linq :

var sl = new List<string>();
// Add strings to sl

var ol = new List<object>(sl.Cast<object>());

// OR
var ol = sl.Cast<object>().ToList();

// OR (note that the cast to object here is required)
var ol = sl.Select(s => (object)s).ToList();
请先 登录 后评论
Tamas Czinege

Oui, vous pouvez, à partir de .NET 3.5 :

List<string> sl = new List<string>();
List<object> ol = sl.Cast<object>().ToList();
请先 登录 后评论
MattValerio

Je pense que cette (contravariance) sera en fait prise en charge en C

请先 登录 后评论
  • 17 abonnés
  • 0 favoris,495 Feuilleter
  • Matt Sheppard posée à 2023-03-27 18:28