C# LINQ如何根据给定的条件对项目进行排序?
假设我们有一个C# LINQ如何根据给定的条件对项目进行排序?,c#,.net,linq,C#,.net,Linq,假设我们有一个MyData类,它实现了IComparable和IComparable接口。然后我们有一个包含许多MyData元素的列表和一个LINQ查询来获得一个排序列表 public class MyData : IComparable<MyData>, IComparable { ... public int CompareTo(MyData value) { // TODO } public int CompareTo
MyData
类,它实现了IComparable
和IComparable
接口。然后我们有一个包含许多MyData
元素的列表和一个LINQ查询来获得一个排序列表
public class MyData : IComparable<MyData>, IComparable
{
...
public int CompareTo(MyData value)
{
// TODO
}
public int CompareTo(object value)
{
if (value == null)
return 1;
if (value.GetType() == typeof(MyData))
{
MyData rightValue = (MyData)value;
return (this.CompareTo(rightValue));
}
else throw new ArgumentException("Object is not a " + typeof(MyData) + ".");
}
}
// main method
List<MyData> list = new List<MyData>();
...
var items = from item in list
orderby item descending
select item;
公共类MyData:IComparable,IComparable
{
...
公共整数比较(MyData值)
{
//待办事项
}
公共整数比较(对象值)
{
如果(值==null)
返回1;
if(value.GetType()==typeof(MyData))
{
MyData rightValue=(MyData)值;
返回(this.CompareTo(rightValue));
}
否则抛出新的ArgumentException(“对象不是“+typeof(MyData)+”);
}
}
//主要方法
列表=新列表();
...
var items=来自列表中的项
按项目降序
选择项目;
当LINQ对列表中的元素进行排序时,它是否在MyData
类中使用IComparable
接口的实现
如果答案是肯定的,那么最好将排序条件封装在类MyData
(通过实现上述接口)中,还是在LINQ查询中指定条件(没有实现这些接口的MyData
)?这两种选择的优缺点是什么?使用默认比较器比较键,而默认比较器将使用您的IComparable
实现
如果答案是肯定的,那么最好将排序条件封装在类MyData中(通过实现上述接口),还是在LINQ查询中指定条件(没有实现这些接口的MyData)?这两种选择的利弊是什么
首先,答案是肯定的
这两种方法都有优点
实现IComparable
表明该类型具有自然顺序。如果这是真的,我喜欢实现这个接口。就LINQ而言,主要优点是简化了LINQ查询(稍微)。然而,我的主要主张是为给定类型建议一个“自然”顺序,这反过来又增加了API的清晰度
在LINQ查询本身中指定条件的主要优点是灵活性。这允许您按任意数量的条件进行排序,而不是将自己限制为在类型本身中定义的给定排序。如果类型没有一个“自然”排序顺序(即:它不表示某个“数量”本身或类似的东西),那么我个人会使用这种方法。OrderBy
扩展方法采用Func
委托-这是用来选择用于排序的项的方法。其中一个重载使用一个IComparer
实例来进行比较,即不使用Default
比较器的实例
看看Edulink——Jon Skeet对LINQ的教育性重新实现,看看这是如何实现的。在本例中,它使用了默认比较器:
此方法使用默认比较器default来比较键
此方法执行稳定排序;也就是说,如果两个
元素相等时,保留元素的顺序。在里面
相反,不稳定排序不能保持元素的顺序
有相同的钥匙
可能需要注意的是,如果您使用的是Linq2SQL或其他LINQ提供程序,情况未必如此。这只适用于IEnumerable实现(Linq2Objects)。+1表示“自然排序”参数。我唯一想补充的是,当一个类型真正具有多个自然排序时,可以使用重载,它接受一个
IComparer
作为参数。这是最常用的StringComparer
@enzom83,性能差异可能可以忽略不计。在这两种情况下,都使用了比较器.Default
,因此性能可能主要是由于比较器的性能与返回的特定成员的默认比较器的性能不同。