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

时间:2010-01-18 21:55:57

标签: c# asp.net linq 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;
            }
        }

3 个答案:

答案 0 :(得分: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;
    }
}

注意我是如何从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();
}

这仍然是相当低效的(因为它使用反射),但至少它没有为每个项目分别获得FieldInfo。如果想要更好的性能,可以使用通用帮助器类型来缓存委托,将值映射到每个字段的字段值,然后在方法开始时获取该委托一次。肯定会有更多的工作,但我希望它会快一个数量级。

答案 1 :(得分:2)

public static List<T> SortResults( List<T> listObject, string sortColumn, bool ascending) where T: class

然后你的ToList将是ToList<T>();

T表示您的实体/对象类型。

答案 2 :(得分:1)

您需要使方法本身通用:

public static List<Row> SortResults<Row>( List<Row> listRow, ...
                                   ^^^^^