How would you convert between List<Object> -> ObjectList and ObjectList -> List(Object) using generics
I find that I need to write the same code in many classes. The code has to do with conversion between types. As I am not familiar with generics, would someone suggest how to convert the follo开发者_JAVA技巧wing to use generics:
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;
}
}
Well, your code snippet is using generics.
Perhaps your impression is that generics are abstract in some sense and must be implemented to be of any use, but if that's the case you are (happily!) mistaken.
Just delete your WidgetManager
and WidgetList
classes. You can use List<Widget>
without any additional complexity. For example:
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);
Here's the magic:
Add an extension to 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;
}
}
The above will copy the contents of the IEnumerable list T1 to the new List Container object T2 and return it.
Just to test:
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();
It looks like you're already using generics, so maybe I'm not understanding the question. The generic List<T>
gives you the strong-typing of the list contents as Widgets at the point where you declare the generic type T to be a Widget, so unless there's some explicit reason why you need the WidgetList object, that class (and the WidgetManager) are superfluous.
List<T>
is not abstract, so you can accomplish everything that's shown here with just the Widget class...then when you need a list of Widgets, you can just create a List<Widget>
.
I will assume you absolutely need a custom collection object (WidgetList), but see note at bottom of the answer if you are not sure. In that case what I would recommend is the following:
- Have
WidgetList
implementIList<Widget>
rather than deriving fromList<Widget>
. Else, it's rather pointless. You can still useList<Widget>
as the implementation. - Since
IList<Widget>
is also anIEnumerable<Widget>
, you will haveToList<Widtget>()
, for free with Linq extensions. - Also make sure you have a
WidgetList
constructor taking anIEnumerable<Widget>
rather than a fonction in a different class. - An
AddRange(IEnumerable<Widget>)
is also very useful.
On a side note, you don't need a WidgetList
if all it does is exactly the same a List<Widget>
. Just use a List<Widget>
directly instead, they offer all the typing that is provided by collection objects. I know you will find a lot of those collection objects in the framework library, but they are there either because they existed before generics, or because they have additional behaviours on Add
and Remove
.
Just a clarification to the question - since I'm also on sme's team. The reason for the strongly typed WidgetList is because we use the XML deserializer to convert a list of widgets from XML passed from our database:
<Widgets>
<Widget>
<Id>1</Id>
<Name>Kitten Kung-Foo</Id>
</Widget>
<Widget>
<Id>2</Id>
<Name>Puppy Punches</Name>
</Widget>
<Widgets>
So here's the same code again with the XML attributes:
[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;
}
}
I'm pretty sure we need the WidgetList in order for the Deserializer to pick up on the fact that there is a collection of Widgets.
Maybe not?
精彩评论