Comment diffuser une liste efficacement?

j’ai un

List 

mais j’ai besoin d’un

 List 

Existe-t-il un moyen de lancer ceci en c #? Ou utilisez Linq pour obtenir le même résultat?

J’ai deux classes qui implémentent la même interface:

 interface IDataField { } class InputField : IDataField { } class PurchaseField : IDataField { } 

Cette liste provient d’une requête Linq-to-Sql:

 List list = (from i .... select i).ToList(); 

.OfType et .Cast renverront une liste de T, mais la signification des deux méthodes est différente.

list.OfType filtre la liste d’origine, renvoie tous les éléments de type T et ignore ceux qui ne le sont pas.

list.Cast convertit tous les éléments de la liste d’origine en type T et lève une exception pour les éléments qui ne peuvent pas être convertis en ce type.

Dans votre cas, les deux donneraient le même résultat, mais utiliser .Cast communiquerait votre intention beaucoup plus clairement, je vous recommande donc de l’utiliser.

 List list = (from i .... select i).Cast.ToList(); 
 List raw = (from i .... select i).ToList(); List result = raw.OfType().ToList(); 

Vous pouvez également utiliser List.ConvertAll .

Documentation: http://msdn.microsoft.com/en-us/library/73fe8cwf.aspx

Exemple:

 List newList = oldList.ConvertAll(i => i as IDataField); 

Depuis la liste vient de

 List list = (from i .... select i).ToList(); 

Ne pourriez-vous pas simplement corriger la partie “select i” pour renvoyer IDataField à la place? Quelque chose comme ça:

 List list = (from i .... select (IDataField)i).ToList(); 

Si cela ne fonctionne pas, peut-être que l’extension “Cast” de IEnumerable fonctionnera:

 List list2 = list.Cast(); 

Juste au cas où: j’ai peu d’expérience C #, mais si cette construction générique signifie la même chose qu’elle le fait en Java, vous devez créer une toute nouvelle liste paramétrée par le supertype. En d’autres termes, si chaque instance de Bangle est également une instance d’ Akthud , il ne s’ensuit pas que chaque List est également une List .

La raison en est que vous pouvez avoir deux références à cette List . Si la deuxième référence jette et ensuite la désigne comme une List , il est autorisé de lui append un Akthud – mais à présent, la première référence a une List dont les membres ne sont pas tous des Bangle s. Violation!

Cela étant dit, la réponse de David B devrait en effet faire ce que vous voulez, correctement, AFAICT. (Cela ressemble à une opération de copie.)

[Et si je ne comprends pas bien la sémantique des génériques C #, j’espère que quelqu’un me corrigera dans un commentaire!]

Je ne sais pas si une dissortingbution directe aurait l’effet souhaité. Les rares fois où je l’ai fait, c’est généralement quelque chose comme:

 List list = ..... List list2 = new (List((IDataField[])list.ToArray())); 

ConvertAll semble être une meilleure solution, car elle ne dépend pas de la bibliothèque Linq, elle est plus courte et plus intuitive.

Mais les deux sont plutôt des solutions de contournement que des solutions. Les deux créent une nouvelle collection avec les mêmes données. Il devrait exister un support pour la covariance générique dans .net, c’est-à-dire la conversion ascendante dans les collections génériques, ce qui vous permettrait de le faire naturellement. Par exemple:

 List ls = (List)List 

D’après mes recherches, ma conclusion est que .Net à partir de la version 3.5 ne prend pas en charge cette fonctionnalité. Par conséquent, nous devons nous retrouver avec des solutions de contournement.

Ce sont les discussions sur le sujet:

  • Covariance générique C #
  • Liste des génériques covariants
  • Les génériques sont-ils Covariant, Contre-Variant ou Invariant?