List implémente IList donc j'espère que IList acceptera un objet List mais pourquoi IList> n'accepte pas List>?
static IList<int> List_1() { List<int> list = new List<int> { 1,2,3,3,4,5}; return list; } static IList<IList<int>> List_2() { List<List<int>> parent = new List<List<int>>(); List<int> list = new List<int> { 1, 2, 3, 3, 4, 5 }; parent.Add(list); return parent; //compiler error CS0266 }
5 Réponses :
Pourquoi alors List implémente IList?
C'est un peu étrange, car List pour tout type autre que object ne remplir l'intégralité du contrat d'IList. C'est probablement pour faciliter les choses les personnes qui mettent à jour l'ancien code C # 1.0 pour utiliser des génériques; ces gens assuraient probablement déjà que seuls les bons types entraient leurs listes. Et la plupart du temps, lorsque vous passez un IList, c'est pour que l'appelé puisse accéder par index à la liste, pas pour que il peut ajouter de nouveaux éléments de type arbitraire.
Supposons que cela fonctionne. Votre code client est:
static IEnumerable<IEnumerable<int>> List_2() { List<List<int>> parent = new List<List<int>>(); List<int> list = new List<int> { 1, 2, 3, 3, 4, 5 }; parent.Add(list); return parent; // no error, this works }
Puisque le contrat permet d'ajouter au résultat tout ce qui est IList
, vous pourriez éventuellement avoir
var result = List_2(); result.Add( new MyCustomIList() );
puis
public class MyCustomIList : IList<int> { ... }
Mais c'est faux!
Votre résultat
est une liste de List
, vous ne devriez pas être autorisé à ajouter autre chose que List
MyCustomIList
qui n'est pas lié à la List
.
Si vous avez besoin une vue d'ensemble du problème, en savoir plus sur covariance et contravariance .
Le problème fondamental dans cet exemple particulier vient de l'opération Add
. Si vous n'en avez pas besoin, IEnumerable
fera l'affaire
var result = List_2();
Cela a été déjà couvert .
Je ne sais pas pourquoi vous voulez renvoyer exactement IList
, mais une façon de le faire est d'utiliser Méthode Cast
:
return parent.ConvertAll(x => (IList<int>)x);
Ou ConvertAll ()
method :
static IList<IList<int>> List_2() { List<List<int>> parent = new List<List<int>>(); List<int> list = new List<int> { 1, 2, 3, 3, 4, 5 }; parent.Add(list); return parent.Cast<IList<int>>().ToList(); }
Les deux méthodes seront exécutées tous les éléments, et les cast / convertir dans un type donné, donc je pense qu'il serait préférable de retourner IList
à la place (si c'est possible). >
p >
Le problème vient de votre méthode return type
. Modifiez la signature de votre méthode pour revenir à IList
plutôt que de renvoyer >
IList
static IList<List<int>> List_2() { List<List<int>> parent = new List<List<int>>(); List<int> list = new List<int> { 1, 2, 3, 3, 4, 5 }; parent.Add(list); return parent; //no compiler error }
Maintenant cela fonctionnera bien car votre méthode renvoie maintenant un IList
de List
C'est parce que
List
implémente IList
mais
List
n'implémente pas >
IList
C'est pourquoi votre première méthode fonctionne comme prévu et la seconde non.
Modifiez simplement votre déclaration de la liste dans la deuxième méthode à
List<IList<int>> parent = new List<IList<int>>();
Et c'est le cas de la covariance et de la contravariance.
Les paramètres de type générique supportent la covariance et contravariance mais vous devez définir de cette manière
La covariance et la contravariance sont des termes qui font référence à la capacité d'utiliser un type plus dérivé (plus spécifique) ou un type moins dérivé (moins spécifique) que celui spécifié à l'origine. Les paramètres de type générique prennent en charge la covariance et la contravariance pour offrir une plus grande flexibilité dans l'attribution et l'utilisation de types génériques
Comprenez-vous pourquoi
List
n'accepte pasList
?return (IList>) parent;
@jdweng: Cela ne fonctionnera pas, vous obtiendrez une exception d'exécution.
Copie possible de Pourquoi ne puis-je pas diffuser depuis une liste pour lister
@ SᴇM Il ne s'agit pas de convertir un type en un type d'objet, mais IList et List.
Le double possible de stackoverflow.com/questions/26501312/...
@vsarunov Vous savez bien, ce compilateur donne une erreur, car il ne peut pas convertir de
List
en>
IList>
?@ SᴇM Cela a-t-il à voir avec la conversion de List en List
@vsarunov Oui, car
MyClass
dérivé deobject
, commeList
dérivé deIList code >. Donc si vous avez par exemple une méthode qui retourne
List
, vous ne pouvez pas retournerList
sans cast.