C# 如何在LINQ中始终为空的情况下进行自定义排序?

C# 如何在LINQ中始终为空的情况下进行自定义排序?,c#,linq,C#,Linq,我需要在内存中按升序或降序排列字符串或数字列表。但是,列表可以包含空值,并且所有空值必须出现在数字或字符串之后 也就是说,输入数据可能是: 1, 100, null, 5, 32.3 1100,空,532.3 上升的结果将是 1, 5, 32.3, 100, null 100, 32.3, 5, 1, null 1,5,32.3100,空 降序名单是 1, 5, 32.3, 100, null 100, 32.3, 5, 1, null 100,32.3,5,1,null 关于如何使其工作,您有

我需要在内存中按升序或降序排列字符串或数字列表。但是,列表可以包含空值,并且所有空值必须出现在数字或字符串之后

也就是说,输入数据可能是:

1, 100, null, 5, 32.3 1100,空,532.3 上升的结果将是

1, 5, 32.3, 100, null 100, 32.3, 5, 1, null 1,5,32.3100,空 降序名单是

1, 5, 32.3, 100, null 100, 32.3, 5, 1, null 100,32.3,5,1,null
关于如何使其工作,您有什么想法吗?

您可以编写自己的比较器,将非空比较器委托给现有比较器,但总是在最后对空比较器进行排序。大概是这样的:

public class NullsLastComparer<T> : IComparer<T>
{
    private readonly IComparer<T> proxy;

    public NullsLastComparer(IComparer<T> proxy)
    {
        this.proxy = proxy;
    }

    public override int Compare(T first, T second)
    {
        if (first == null && second == null)
        {
            return 0;
        }
        if (first == null)
        {
            return 1;
        }
        if (second == null)
        {
            return -1;
        }
        return proxy.Compare(first, second);
    }
}
公共类NullsLastComparer:IComparer
{
专用只读IComparer代理;
公共NullsLastComparer(IComparer代理)
{
this.proxy=代理;
}
公共覆盖整数比较(T第一,T第二)
{
if(first==null&&second==null)
{
返回0;
}
if(first==null)
{
返回1;
}
if(秒==null)
{
返回-1;
}
返回proxy.Compare(第一,第二);
}
}
编辑:此方法的几个问题:

首先,它不能很好地处理匿名类型;您可能需要一个单独的扩展方法才能很好地工作。或者使用肯的答案:)

更重要的是,它违反了
IComparer
契约,该契约规定空值应该是第一位的。现在我个人认为这是
IComparer
规范中的一个错误-它可能应该定义比较器应该处理空值,但不应该指定它们是第一个还是最后一个。。。它使得这样的需求(这是完全合理的)不可能像我们希望的那样干净地实现,并且对于像反向比较器这样的东西有各种各样的尴尬的后果。您可能希望这样的事情完全颠倒顺序,但根据规范,它在开始时仍应保持空值:(


我不认为我见过任何.NET排序实现实际上依赖于此,但它确实值得注意。

我面前没有编译器可供检查,但我想:

x.OrderBy(i => i == null).ThenBy(i => i)

正如Jon所说,您需要定义自定义比较器,实现
IComparer
。下面是自定义比较器中的
Compare
方法如何在最后保持
null

    public int Compare(Object x, Object y)
    {
        int retVal = 0;

        IComparable valX = x as IComparable;
        IComparable valY = y as IComparable;

        if (valX == null && valY == null)
        {
            return 0;
        }

        if (valX == null)
        { 
            return 1; 
        }
        else if (valY == null)
        {
            return -1;
        }

        return valX.CompareTo(valY);
    }

这不是违反了与.NET排序实现的合同吗?我想我已经在某个地方读到排序方法可以假定null是第一位的…或者…?@Lasse:这违反了
IComparer
接口,是的-我将编辑我的帖子来提及这一点。是的,但从我读到这篇文章时的记忆来看,听起来像是由于这个契约,排序方法可能会走捷径,因此在某些情况下实际上不会调用比较方法,因为它“知道”结果会是什么。换句话说,在某些情况下,这不会产生奇怪的结果吗?@Lasse:我不能说我见过任何走捷径的方法就像那样…这意味着更多的工作,而不是更少的工作,因为它不会像一般那样对待它。如果你有任何示例,我很想看看它们。不需要输入
I可比较的
?并且构造函数应该被定义为
公共NullsLastComparer(I比较代理)
没有T.Nice…这是一个非常好的方法。如果可以的话,我会不止一次地投票支持这个方法…非常好。这个方法也适用于Linq To实体,并且可以正确地转换为Sql。尽管它是如此简单的解决方案,但对我来说它看起来非常聪明…我正在编写一个自定义比较器。。。