Je pense que cette (contravariance) sera en fait prise en charge en C
Il semble qu'un objet List ne puisse pas être stocké dans une variable List en C
Je pense que cette (contravariance) sera en fait prise en charge en C
Oui, vous pouvez, à partir de .NET 3.5 :
List<string> sl = new List<string>();
List<object> ol = sl.Cast<object>().ToList();
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();
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
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.
Mike - Je crois que la contravariance n'est pas autorisée en C
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
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.