【问题标题】:C# linq sort - quick way of instantiating IComparerC# linq sort - 实例化 IComparer 的快速方法
【发布时间】:2009-09-04 21:12:28
【问题描述】:

当你使用 linq 时,你有

c.Sort()

是否有任何好的内联方式来定义Comparison 和/或IComparer 类而无需实际创建单独的类?

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    这是 lambda 表达式的用途之一:

    c.Sort( (x,y) => x.A.CompareTo(y.A))

    【讨论】:

    • 我认为这对 IComparer 不起作用,因为 lamda 应该返回 int 而不是 bool。
    • 你是对的。这适用于 IComparison,不适用于 IComparable。花一个小时的大部分时间试图让这样的东西与 NUnit CollectionAssert.IsOrdered 方法一起工作,结果却发现它没有。所有的文档和文章都令人困惑,因为它们使用排序方法作为示例。 sort 方法具有采用 IComparer 和 IComparison 的重载。由于 IComparison 重载,这只适用于 sort 方法。
    • @Brett 但在即将推出的 .NET4.5 中,您可以通过调用新的静态工厂方法 Comparer<>.CreateIComparison<> 委托构造 IComparer<> 实例。
    【解决方案2】:

    我在MiscUtil 中有一个ProjectionComparer 类,所以你可以这样做:

    IComparer<Foo> comparer = ProjectionComparer<Foo>.Create(x => x.Name);
    c.Sort(comparer);
    

    代码也在this answer

    您也可以直接使用 lambda 表达式创建 Comparison&lt;T&gt; 实例,但我通常不喜欢其中涉及的重复。话虽如此,它通常最终会变得更短......

    编辑:如前所述,从 .NET 4.5 开始,使用 Comparer&lt;T&gt;.Create 做同样的事情。

    【讨论】:

    • 好吧,如果你看一下接受的答案,它有多余的信息:“A”部分被指定了两次。 (它也不会编译,因为它返回一个 bool 而不是 int,但没关系。)如果它是一个简单的属性,那没关系,但如果它是一个复杂的表达式,那就更痛苦了。
    • @JonSkeet 在新的 .NET 中有类似的东西(创建 IComparer 的实用方法),看我的回答
    • @taras.roshko:在 .NET 4.5 中有现在。没有回到 2009 年 :)
    • 是的,当然,我在回答中提到最终我们在 BCL 中使用了该方法 :)
    【解决方案3】:

    乔恩的回答很棒,但可能有点过时了, 随着 .NET 4.5 的发布,我们现在(终于!)有了这个很棒的方法Comparer&lt;T&gt;.Create

    items.Sort((x, y) => x.Value.CompareTo(y.Value)); //sorting List<T>                
    items.OrderBy(x => x, Comparer<Item>.Create((x, y) => x.Value.CompareTo(y.Value))); //sorting IEnumerable<T>
    

    假设Item 的定义类似于:

    class Item
    {
        public readonly int Key;
        public readonly string Value;
    
        public Item(int key, string value)
        {
            Key = key;
            Value = value;
        }
    }
    

    【讨论】:

      【解决方案4】:

      我不知道您的示例中的c.Sort() 是什么,因为它可以是很多东西(您的意思是List&lt;T&gt;.Sort()?),但它肯定不是LINQ 的一件事。 LINQ 没有 Sort() - 它有 OrderBy()

      也就是说,后者也适用于IComparer,并且无法创建实现接口“内联”的匿名类的实例,因此您必须定义一个类。

      对于List&lt;T&gt;.Sort(),有一个需要Comparison&lt;T&gt; 的重载。由于它是委托类型,您可以使用 lambda 来提供内联函数:

      List<int> xs = ...;
      xs.Sort((x, y) => y - x); // reverse sort
      

      【讨论】:

      • “没有办法创建实现内联接口的匿名类的实例” - 这取决于您的语言。 F# 可以很好地做到这一点。
      • @Joel:问题的标签中明确指定了语言。
      • 当然是。 “无法做到”和“无法在 C# 中做到”之间也有区别。
      • 当回答一个为代码指定语言 X 的问题时,除非另有明确说明,否则问题和答案都暗示“... in language X”。
      • @DavidStorfer,看看我的回答,在 .NET 4.5 中,我们现在可以使用 OrderBy 简单地“指定属性”,这要归功于新的 Comparer.Create 方法
      【解决方案5】:

      如果列表 c 中的对象已经实现了 IComparable,则不需要另一个。 但是如果需要自定义比较,可以在嵌套类中实现 IComparer。 您还可以使用 lambda 表达式动态创建比较方法:

      persons.Sort( (person1, person2) =&gt; person1.Age.CompareTo( person2.Age ) );

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-05
        • 2011-05-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多