我有一个名为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#中执行此操作?
当前回答
我为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#。
顺致敬意,
其他回答
如果需要对Question实体中的字符串Id进行排序使用Sort函数和委托在解析Id后对Id进行排序价值
class Question
{
public List<QuestionInfo> Questions Info{ get; set; }
}
class QuestionInfo
{
public string Id{ get; set; }
public string Questions{ get; set; }
}
var questionnaire = new Question();
questionnaire.QuestionInfo.Sort((x, y) => int.Parse(x.Id, CultureInfo.CurrentCulture) - int.Parse(y.Id, CultureInfo.CurrentCulture));
使用LINQ
objListOrder = GetOrderList()
.OrderBy(o => o.OrderDate)
.ToList();
objListOrder = GetOrderList()
.OrderBy(o => o.OrderId)
.ToList();
要在.Net 2.0上不使用LINQ的情况下执行此操作,请执行以下操作:
List<Order> objListOrder = GetOrderList();
objListOrder.Sort(
delegate(Order p1, Order p2)
{
return p1.OrderDate.CompareTo(p2.OrderDate);
}
);
如果你在.Net 3.0上,那么LukeH的答案就是你在追求什么。
要对多个财产进行排序,您仍然可以在委托中进行排序。例如:
orderList.Sort(
delegate(Order p1, Order p2)
{
int compareDate = p1.Date.CompareTo(p2.Date);
if (compareDate == 0)
{
return p2.OrderID.CompareTo(p1.OrderID);
}
return compareDate;
}
);
这将为您提供具有降序ID的升序日期。
然而,我不建议使用委托,因为这意味着很多地方没有代码重用。您应该实现一个IComparer,并将其传递给Sort方法。请参见此处。
public class MyOrderingClass : IComparer<Order>
{
public int Compare(Order x, Order y)
{
int compareDate = x.Date.CompareTo(y.Date);
if (compareDate == 0)
{
return x.OrderID.CompareTo(y.OrderID);
}
return compareDate;
}
}
然后,要使用这个IComparer类,只需实例化它并将其传递给Sort方法:
IComparer<Order> comparer = new MyOrderingClass();
orderList.Sort(comparer);
下面是一个通用LINQ扩展方法,它不会创建列表的额外副本:
public static void Sort<T,U>(this List<T> list, Func<T, U> expression)
where U : IComparable<U>
{
list.Sort((x, y) => expression.Invoke(x).CompareTo(expression.Invoke(y)));
}
要使用它:
myList.Sort(x=> x.myProperty);
我最近构建了另一个接受ICompare<U>的插件,以便您可以自定义比较。当我需要进行自然字符串排序时,这很有用:
public static void Sort<T, U>(this List<T> list, Func<T, U> expression, IComparer<U> comparer)
where U : IComparable<U>
{
list.Sort((x, y) => comparer.Compare(expression.Invoke(x), expression.Invoke(y)));
}
//用于网格视图的完全通用排序
public List<T> Sort_List<T>(string sortDirection, string sortExpression, List<T> data)
{
List<T> data_sorted = new List<T>();
if (sortDirection == "Ascending")
{
data_sorted = (from n in data
orderby GetDynamicSortProperty(n, sortExpression) ascending
select n).ToList();
}
else if (sortDirection == "Descending")
{
data_sorted = (from n in data
orderby GetDynamicSortProperty(n, sortExpression) descending
select n).ToList();
}
return data_sorted;
}
public object GetDynamicSortProperty(object item, string propName)
{
//Use reflection to get order type
return item.GetType().GetProperty(propName).GetValue(item, null);
}