2010-10-19 3 views
0

Je trouve que j'ai besoin d'écrire le même code dans de nombreuses classes. Le code a à voir avec la conversion entre les types. Comme je ne suis pas familier avec les génériques, ce que quelqu'un suggère comment convertir ce qui suit pour utiliser les médicaments génériques:Comment voulez-vous convertir entre Liste <Object> -> ObjectList et ObjectList -> Liste (Object) en utilisant des génériques

public class WidgetList : List<Widget> { } 

public class Widget 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    public Widget() { } 

    public Widget(int Id, string Name) 
    { 
     this.Id = Id; 
     this.Name = Name; 
    } 
} 

public class WidgetManager 
{ 
    public static List<Widget> ToListType(WidgetList list) 
    { 
     return list.ToList<Widget>(); 
    } 

    public static WidgetList ToTypeList(List<Widget> list) 
    { 
     WidgetList typeList = new WidgetList(); 
     foreach (Widget item in list) 
     { 
      typeList.Add(w); 
     } 

     return typeList; 
    } 
} 
+2

Peut-être que je suis malentendu vos intentions, mais quel est le point de haveing ​​un type WidgetList? WidgetList est une sous-classe vide de la liste donc le seul but réel est de donner un nom spécifique à la liste . – Stephan

+0

Je ne sais pas pourquoi vous subdivisez une 'Liste' générique si vous n'ajoutez pas de fonctionnalité. Y a-t-il une raison pour laquelle vous sub-classer? Pourquoi ne pouvez-vous pas opérer sur une 'Liste '? – linuxuser27

+0

C'est une chose de modèle ... pour nous aider à être des codeurs paresseux. Nous n'ajoutons aucune propriété à WidgetList. C'est simplement une collection. La plupart de notre code consomme la liste. La seule fois que nous devons avoir la liste est lors de l'utilisation de linq pour filtrer les données contenues dans la liste. C'est pourquoi je voudrais écrire des méthodes de conversion génériques. – sme

Répondre

1

est ici la magie:

Ajouter une extension à IEnumerable:

public static class IEnumerableExtensions 
{ 
    public static T2 ToListContainer<T1, T2>(this IEnumerable<T1> list) where T2: List<T1>, new() 
    { 
     T2 listContainer = new T2(); 
     listContainer.AddRange(list); 
     return listContainer; 
    } 

} 

ci-dessus copie le contenu de la liste IEnumerable T1 au nouveau T2 objet Liste des conteneurs et le retourner.

Juste à tester:

WidgetList widgets = new WidgetList(); 

widgets.Add(new Widget(1, "Dog 1")); 
widgets.Add(new Widget(2, "Dog 2")); 
widgets.Add(new Widget(3, "Dog 3")); 
widgets.Add(new Widget(4, "Cat 1")); 
widgets.Add(new Widget(5, "Dog 2")); 
widgets.Add(new Widget(6, "Dog 3")); 


widgets = (from w in widgets 
      where w.Name.Contains("1") 
      select w).ToListContainer<Widget, WidgetList>(); 

int c = widgets.Count(); 
0

On dirait que vous utilisez déjà des médicaments génériques, alors peut-être je ne comprends pas la question. Le List<T> générique vous donne la typage fort du contenu de la liste en tant que Widgets au moment où vous déclarez le type générique T comme Widget, donc à moins d'une raison explicite pour laquelle vous avez besoin de l'objet WidgetList, cette classe (et le WidgetManager) sont superflus.

List<T> n'est pas abstrait, donc vous pouvez accomplir tout ce qui est montré ici avec juste la classe Widget ... alors quand vous avez besoin d'une liste de Widgets, vous pouvez simplement créer un List<Widget>.

0

Je suppose que vous avez absolument besoin d'un objet de collection personnalisé (WidgetList), mais voir la note au bas de la réponse si vous n'êtes pas sûr. Dans ce cas, ce que je recommande est la suivante:

  • Avez WidgetList mettre en œuvre IList<Widget> plutôt que de tirer List<Widget>. Sinon, c'est plutôt inutile. Vous pouvez toujours utiliser List<Widget> comme implémentation.
  • Depuis IList<Widget> est également un IEnumerable<Widget>, vous aurez ToList<Widtget>(), gratuitement avec les extensions Linq.
  • Vérifiez également que vous avez un constructeur WidgetList prenant un IEnumerable<Widget> plutôt qu'une fonction dans une classe différente. Un AddRange(IEnumerable<Widget>) est également très utile.

Sur une note de côté, vous n'avez pas besoin WidgetList si tout ce qu'il fait est exactement la même un List<Widget>. Il suffit d'utiliser directement un List<Widget>, ils offrent tout le typage fourni par les objets de collection. Je sais que vous trouverez beaucoup de ces objets de collection dans la bibliothèque de framework, mais ils sont là soit parce qu'ils existaient avant les génériques, soit parce qu'ils ont des comportements supplémentaires sur Add et Remove.

2

Eh bien, votre extrait de code est en utilisant des génériques. Vous avez peut-être l'impression que les génériques sont abstraits dans un certain sens et doivent être mis en œuvre pour être utiles, mais si c'est le cas, vous vous trompez (heureusement!). Il suffit de supprimer vos classes WidgetManager et WidgetList. Vous pouvez utiliser List<Widget> sans complexité supplémentaire. Par exemple:

var widgets = new List<Widget>(); 

widgets.Add(new Widget(42, "foo")); 
widgets.Add(new Widget(43, "bar")); 

foreach (var widget in widgets) 
    Console.WriteLine("{0}: {1}", widget.Id, widget.Name); 
0

Juste une clarification à la question - puisque je suis également sur l'équipe de sme.La raison de l'fortement typé WidgetList est parce que nous utilisons le désérialiseur XML pour convertir une liste de widgets de XML passé de notre base de données:

<Widgets> 
<Widget> 
    <Id>1</Id> 
    <Name>Kitten Kung-Foo</Id> 
</Widget> 
<Widget> 
    <Id>2</Id> 
    <Name>Puppy Punches</Name> 
</Widget> 
<Widgets> 

Voici donc le même code à nouveau avec les attributs XML:

[XmlType("Widgets"), Serializable] 
public class WidgetList : List<Widget> { } 

[XmlType("Widget"), Serializable] 
public class Widget 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    public Widget() { } 

    public Widget(int Id, string Name) 
    { 
     this.Id = Id; 
     this.Name = Name; 
    } 
} 

Je suis sûr que nous avons besoin de la WidgetList pour que le Deserializer prenne conscience du fait qu'il y a une collection de Widgets.

Peut-être que non?