jam*_*one 1 c# linq asp.net generics
我不太清楚我是否理解如何正确使用C#中的泛型.说我有以下方法.我想允许它在任何类型的列表上工作.目前我有List其中Row是一个自定义结构,我想重用这个排序方法为我做的六个结构.我以为我可以List<T>在返回类型和参数类型中做,但它不喜欢这样.
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;
}
}
Run Code Online (Sandbox Code Playgroud)
好吧,这是你的原始代码通用:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
注意我是如何从ToList调用中删除类型参数的- 让编译器解决它:)
(顺便说一句,我不知道为什么编译器需要一个default案例.也许它总是假设会有未列出的潜在价值.)
但是,这可以更好:
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();
}
Run Code Online (Sandbox Code Playgroud)
这仍然是相当低效的(因为它使用反射),但至少它没有FieldInfo为每个项目单独获取.如果想要更好的性能,可以使用通用帮助器类型来缓存委托,将值映射到每个字段的字段值,然后在方法开始时获取该委托一次.肯定会有更多的工作,但我希望它会快一个数量级.