我有一个名为Order的类,它具有OrderId、OrderDate、Quantity和Total等财产。我有这个订单类的列表:

List<Order> objListOrder = new List<Order>();
GetOrderList(objListOrder); // fill list of orders

我想根据Order对象的一个属性对列表进行排序;例如通过订单日期或订单id。

如何在C#中执行此操作?


当前回答

我为List<T>制作了这个扩展方法。

扩展方法将您希望排序的属性作为解析字符串,然后使用List<T>的OrderBy方法。然后,它将原始列表的每个索引设置为有序列表的相同索引。

public static class ListExtensions {
    public static void SortBy<T>(this List<T> list, string property, bool reverse = false) {
        List<T> ordered = list.OrderBy(obj => obj.GetType().GetProperty(property).GetValue(obj, null)).ToList();
            
        for (int i = 0; i < list.Count; i++)
            list[i] = reverse ? ordered[list.Count - 1 - i] : ordered[i];
    }
}

如果列表中的对象具有属性Name,则按如下方式对列表testList进行排序:

//For normal sorting order
testList.SortBy("Name");
//For reverse sorting order
testList.SortBy("Name", true);

我建议您将SortBy的名称更改为Prefix_SortBy。若要防止导入其他库时可能发生冲突。

我知道这种方法适用于字母和数字排序。其分选能力可能有限,但操作非常简单。

如果有一些重大的缺陷或问题,请告诉我,我已经编写了大约3个月的C#。

顺致敬意,

其他回答

//Get data from database, then sort list by staff name:

List<StaffMember> staffList = staffHandler.GetStaffMembers();

var sortedList = from staffmember in staffList
                 orderby staffmember.Name ascending
                 select staffmember;
var obj = db.Items.Where...

var orderBYItemId = obj.OrderByDescending(c => Convert.ToInt32(c.ID));

如果需要对列表进行排序,则可以使用sort方法,传递Comparison<T>委托:

objListOrder.Sort((x, y) => x.OrderDate.CompareTo(y.OrderDate));

如果您希望创建一个新的排序序列而不是就地排序,那么可以使用LINQ的OrderBy方法,如其他答案中所述。

从性能的角度来看,最好使用排序列表,以便在将数据添加到结果中时对其进行排序。其他方法至少需要对数据进行一次额外的迭代,并且大多数方法都会创建数据的副本,这样不仅会影响性能,还会影响内存使用。数百个元素可能不会有问题,但数千个元素可能会有问题,特别是在许多并发请求可能同时进行排序的服务中。查看System.Collections.Generic命名空间,然后选择一个带有排序的类,而不是List。

尽可能避免使用反射的通用实现,这也会导致性能问题。

基于GenericTypeTea的比较器:我们可以通过添加排序标志来获得更多的灵活性:

public class MyOrderingClass : IComparer<Order> {  
    public int Compare(Order x, Order y) {  
        int compareDate = x.Date.CompareTo(y.Date);  
        if (compareDate == 0) {  
            int compareOrderId = x.OrderID.CompareTo(y.OrderID);  

            if (OrderIdDescending) {  
                compareOrderId = -compareOrderId;  
            }  
            return compareOrderId;  
        }  

        if (DateDescending) {  
            compareDate = -compareDate;  
        }  
        return compareDate;  
    }  

    public bool DateDescending { get; set; }  
    public bool OrderIdDescending { get; set; }  
}  

在此场景中,必须将其显式实例化为MyOrderingClass(而不是IComparer)为了设置其排序财产:

MyOrderingClass comparer = new MyOrderingClass();  
comparer.DateDescending = ...;  
comparer.OrderIdDescending = ...;  
orderList.Sort(comparer);