我有一个名为Order的类,它具有OrderId、OrderDate、Quantity和Total等财产。我有这个订单类的列表:
List<Order> objListOrder = new List<Order>();
GetOrderList(objListOrder); // fill list of orders
我想根据Order对象的一个属性对列表进行排序;例如通过订单日期或订单id。
如何在C#中执行此操作?
我有一个名为Order的类,它具有OrderId、OrderDate、Quantity和Total等财产。我有这个订单类的列表:
List<Order> objListOrder = new List<Order>();
GetOrderList(objListOrder); // fill list of orders
我想根据Order对象的一个属性对列表进行排序;例如通过订单日期或订单id。
如何在C#中执行此操作?
当前回答
从性能的角度来看,最好使用排序列表,以便在将数据添加到结果中时对其进行排序。其他方法至少需要对数据进行一次额外的迭代,并且大多数方法都会创建数据的副本,这样不仅会影响性能,还会影响内存使用。数百个元素可能不会有问题,但数千个元素可能会有问题,特别是在许多并发请求可能同时进行排序的服务中。查看System.Collections.Generic命名空间,然后选择一个带有排序的类,而不是List。
尽可能避免使用反射的通用实现,这也会导致性能问题。
其他回答
我能想到的最简单的方法是使用Linq:
List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList();
使用LiNQ OrderBy
List<Order> objListOrder=new List<Order> ();
objListOrder=GetOrderList().OrderBy(o=>o.orderid).ToList();
经典的面向对象解决方案
首先,我必须向LINQ的伟大致敬。。。。现在我们已经把它排除在外了
JimmyHoffa答案的变体。使用泛型时,CompareTo参数变为类型安全。
public class Order : IComparable<Order> {
public int CompareTo( Order that ) {
if ( that == null ) return 1;
if ( this.OrderDate > that.OrderDate) return 1;
if ( this.OrderDate < that.OrderDate) return -1;
return 0;
}
}
// in the client code
// assume myOrders is a populated List<Order>
myOrders.Sort();
当然,这个默认的可排序性是可重用的。也就是说,每个客户端不必冗余地重新写入排序逻辑。交换“1”和“-1”(或逻辑运算符,由您选择)可反转排序顺序。
您可以对财产选择做一些更通用的操作,但也可以对您选择的类型进行特定操作,例如“订单”:
将函数编写为通用函数:
public List<Order> GetOrderList<T>(IEnumerable<Order> orders, Func<Order, T> propertySelector)
{
return (from order in orders
orderby propertySelector(order)
select order).ToList();
}
然后这样使用:
var ordersOrderedByDate = GetOrderList(orders, x => x.OrderDate);
您可以更加通用,并为您想要订购的产品定义一个开放类型:
public List<T> OrderBy<T,P>(IEnumerable<T> collection, Func<T,P> propertySelector)
{
return (from item in collection
orderby propertySelector(item)
select item).ToList();
}
并以相同的方式使用:
var ordersOrderedByDate = OrderBy(orders, x => x.OrderDate);
这是一种愚蠢而不必要的复杂LINQ风格的“OrderBy”方式,但它可能会给你一个如何以通用方式实现的线索
基于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);