使用泛型使方法适用于任何数据类型

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)

Jon*_*eet 8

好吧,这是你的原始代码通用:

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为每个项目单独获取.如果想要更好的性能,可以使用通用帮助器类型来缓存委托,将值映射到每个字段的字段值,然后在方法开始时获取该委托一次.肯定会有更多的工作,但我希望它会快一个数量级.