香港专业教育学院一直试图在LINQ语句中获取OrderBy以使用匿名对象,但到目前为止已经失败了。

我已经检查了这些:
Anonymous IComparer implementation
C# linq sort - quick way of instantiating IComparer
How to sort an array of object by a specific field in C#?

我花了几个小时尝试不同的方法,但是必须缺少一些东西。

假设有以下类(class):

public class Product
{
   public int Id {get; set;}
   public string Name {get; set;}
   public int Popularity {get; set;}
   public decimal Price {get; set;}
}
products是这些对象的列表。

我如何完成此LINQ语句,使其可与匿名对象一起使用?
明确地说,我知道我可以用不同的方式来做到这一点,但是我非常有兴趣学习如何使这个特定的示例生效。
var sortedProducts = products
                       .OrderBy(p =>
                              new {p.Popularity, p.Price},
                              [IComparer magic goes here]);

似乎可以通过ProjectionComparer的实现来实现:
http://code.google.com/p/edulinq/source/browse/src/Edulinq/ProjectionComparer.cs?r=0c583631b709679831c99df2646fc9adb781b2be

任何想法如何做到这一点?

更新:

我对此进行了快速性能测试-匿名比较器解决方案与标准orderby.thenby,看来匿名解决方案的运行速度相当慢,这可能还是我们所期望的。
         numProd  | Anon    | chained orderby clauses
         10 000   | 47 ms   | 31 ms
         100 000  | 468 ms  | 234 ms
         1 000 000| 5818 ms | 2387 ms
         5 000 000| 29547 ms| 12105 ms

最佳答案

您可以创建一个IComparer<T>实现,该实现使用您提供的用于比较的委托(delegate),并使用类型推断将其实例化(类似于“通过示例广播”):

static class AnonymousComparer
{
    public static IComparer<T> GetComparer<T>(T example, Comparison<T> comparison)
    {
        return new ComparerImpl<T>(comparison);
    }
    private class ComparerImpl<T> : IComparer<T>
    {
        private readonly Comparison<T> _comparison;
        public ComparerImpl(Comparison<T> comparison) { _comparison = comparison; }
        public int Compare(T x, T y) { return _comparison.Invoke(x, y); }
    }
}

并以此方式使用它:
var comparer = AnonymousComparer.GetComparer(
    new { Popularity = 0, Price = 0m },
    (a, b) => //comparison logic goes here
    );

var sortedProducts = products
    .OrderBy(p =>
        new { p.Popularity, p.Price },
        comparer);

编辑:我只是 checkout 您链接到的投影比较器页面。使用这种方法,您不需要“example”自变量进行类型推断。但是,仍然需要对方法进行调整,以采用委托(delegate)代替接口(interface)。这里是:
//adapted from http://code.google.com/p/edulinq/source/browse/src/Edulinq/ProjectionComparer.cs?r=0c583631b709679831c99df2646fc9adb781b2be
static class AnonymousProjectionComparer
{
    private class ProjectionComparer<TElement, TKey> : IComparer<TElement>
    {
        private readonly Func<TElement, TKey> keySelector;
        private readonly Comparison<TKey> comparison;

        internal ProjectionComparer(Func<TElement, TKey> keySelector, Comparison<TKey> comparison)
        {
            this.keySelector = keySelector;
            this.comparison = comparison ?? Comparer<TKey>.Default.Compare;
        }

        public int Compare(TElement x, TElement y)
        {
            TKey keyX = keySelector(x);
            TKey keyY = keySelector(y);
            return comparison.Invoke(keyX, keyY);
        }
    }

    public static IComparer<TElement> GetComparer<TElement, TKey>(Func<TElement, TKey> keySelector, Comparison<TKey> comparison)
    {
        return new ProjectionComparer<TElement, TKey>(keySelector, comparison);
    }
}

关于c# - LINQ OrderBy具有投影比较器的匿名对象,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10356864/

10-13 08:08