有没有更简洁的方法可以在C#中进行排序?

时间:2010-08-19 19:16:03

标签: c# .net sorting

假设我有一个像:

这样的实体
public class Car
{
    public string Make { get; set; }
    public string Model { get; set; }
    public DateTime ReleaseDate { get; set; }
    public int NumCreated { get; set; }
}

我们正在为我们的网站使用一个简单的MVP架构,其中包含一个视图层(ASP.NET网站,Presenter Layer(C#类库),逻辑层(C#类库),数据层(C#类库)。

假设我有一个显示带有可排序列标题的汽车列表的视图。我过去一直在做的是在逻辑层中进行所有排序,并且视图传递枚举,无论实体列表需要排序的列是什么。

这很痛苦,因为我需要为我拥有的每个实体维护一个枚举,并为该实体中的每个属性保留该枚举中的一个条目。

因此,例如,我们会做类似的事情:

CarLogic.cs

public IEnumerable<Car> GetCarsByYear(string year, SortColumn sortColumn, SortOrder sortOrder)
{
    List<Car> cars = _carRepository.GetCarsByYear(year);  

    switch (sortColumn)
    {
        case SortColumn.Make:
            cars.Sort((car1, car2) =>
                    sortOrder == SortOrder.Ascending
                    ? car1.Make.CompareTo(car2.Make) :
                      car2.Make.CompareTo(car1.Make);
            break;
       case SortColumn.Model:
            cars.Sort((car1, car2) =>
                    sortOrder == SortOrder.Ascending
                    ? car1.Model.CompareTo(car2.Model) :
                      car2.Model.CompareTo(car1.Model);
            break;
       case SortColumn.ReleaseDate:
            cars.Sort((car1, car2) =>
                    sortOrder == SortOrder.Ascending
                    ? car1.ReleaseDate.CompareTo(car2.ReleaseDate) :
                      car2.ReleaseDate.CompareTo(car1.ReleaseDate);
            break;
       case SortColumn.NumCreated:
            cars.Sort((car1, car2) =>
                    sortOrder == SortOrder.Ascending
                    ? car1.NumCreated.CompareTo(car2.NumCreated) :
                      car2.NumCreated.CompareTo(car1.NumCreated);
            break;
       // ...
    }

    return cars;
}

这就是我一直这样做的。但是,这是一个非常手动的过程,如果一个实体有很多属性,那就很烦人了。

处理此问题的更好方法是什么?是否可以允许我的实体集合在属性上进行排序,而不必像这样手动执行所有属性?

4 个答案:

答案 0 :(得分:12)

处理它的更好方法是:

public IEnumerable<Car> GetCarsByYear<T>(string year, SortOrder sortOrder,
    Func<Car, T> fieldSelector) where T : IComparable<T>
{
    List<Car> cars = _carRepository.GetCarsByYear(year);  

    cars.Sort((car1, car2) =>
        sortOrder == sortOrder.Ascending
        ? fieldSelector(car1).CompareTo(fieldSelector(car2)) :
          fieldSelector(car2).CompareTo(fieldSelector(car1)));

    return cars;
}

GetCarsByYear(2010, SortOrder.Ascending,  c => c.Model);
GetCarsByYear(2008, SortOrder.Descending, c => c.Make);

正如上面提到的海报,使用OrderBy而不是将其存放在列表中也更为自然。

答案 1 :(得分:0)

您可以使用LINQ to Objects对您的实体执行排序

var sortedCars = cars.OrderBy(c => c.Model).ThenBy(c => c.Make);

或者您也可以使用OrderByDescendingThenByDescending进行排序。

答案 2 :(得分:0)

使用IComparer类对集合进行排序会更简单吗?

答案 3 :(得分:0)

我能想到的最好的方法是使用方法

    static List<T> SortList<T>(List<T> list, string column)
    {
        foreach (PropertyInfo p in typeof(T).GetProperties())
        {
            if (p.Name == column)
            {
                return list.OrderBy(c => c.GetType().GetProperty(p.Name).GetValue(c, null)).ToList();
            }
        }
        return list;
    }

然后可以使用

调用它
var sortedList = SortList<Car>(cars, "NumCreated");

由于它使用反射,它将适用于任何不必更改的对象的列表。