Use generics to make a method work for any data type
I'm not quite sure I'm understanding how I can utilize generics in C# properly. Say I have the following method. I would like to allow it to work on Lists of any type. Currently I have List where Row is a custom struct, I want to reuse this sort method for half a dozen structs that I make. I thought I could just do List<T>
in the return type and parameter t开发者_如何学编程ype but it doesn't like that.
public static List<Row> SortResults( List<Row> listRow, string sortColumn, bool ascending)
{
switch (ascending)
{
case true:
return (from r in listRow
orderby r.GetType().GetField(sortColumn).GetValue(r)
select r).ToList<Row>();
case false:
return (from r in listRow
orderby r.GetType().GetField(sortColumn).GetValue(r) descending
select r).ToList<Row>();
default:
return listRow;
}
}
Well, here's your original code made generic:
public static List<T> SortResults<T>(List<T> listRow,
string sortColumn, bool ascending)
{
switch (ascending)
{
case true:
return (from r in listRow
orderby r.GetType().GetField(sortColumn).GetValue(r)
select r).ToList();
case false:
return (from r in listRow
orderby r.GetType().GetField(sortColumn).GetValue(r) descending
select r).ToList();
default:
return listRow;
}
}
Note how I've removed the type argument from the ToList
calls - let the compiler work it out :)
(As an aside, I don't know why the compiler requires a default
case here. Maybe it just always assumes there will be unlisted potential values.)
However, this can be made nicer:
public static List<T> SortResults<T>(List<T> listRow,
string sortColumn,
bool ascending)
{
FieldInfo field = typeof(T).GetField(sortColumn);
Func<T, object> projection = t => field.GetValue(t);
IEnumerable<T> sequence = ascending ? listRow.OrderBy(projection)
: listRow.OrderByDescending(projection);
return sequence.ToList();
}
This is still fairly inefficient (as it's using reflection) but at least it's not getting the FieldInfo
separately for each item. If you want better performance, you can have a generic helper type which caches a delegate mapping a value to the field's value for each field, and then fetch that delegate once at the start of the method. It would definitely be more work, but I'd expect it to be an order of magnitude faster.
public static List<T> SortResults( List<T> listObject, string sortColumn, bool ascending) where T: class
Then your ToList would be ToList<T>();
T represents your entity/object type.
You need to make the method itself generic:
public static List<Row> SortResults<Row>( List<Row> listRow, ...
^^^^^
精彩评论