如何在Linq OrderBy子句中应用默认的IComparable <t> </t>

时间:2012-08-09 09:44:18

标签: linq sql-order-by icomparablet

我有一个类型,它在实现IComparable<T>IComparable时具有默认排序顺序。我没有得到我期望从LINQ获得的结果,基本上看起来好像该类型实现的IComparable<T>没有被应用。

我以为我会在表格中得到我想要的结果:

var result = MyEnumerable<T>.OrderBy(r => r); 

T本身实现IComparable<T>。它没有发生。

我可以看到为排序指定了特定IComparable<T>类的相关问题,但我找不到使用IComparable<T>本身实现的默认T的问题。

我的语法显然不正确。请问正确的语法是什么?

提前致谢。

2 个答案:

答案 0 :(得分:3)

OrderBy使用默认的比较器Comparer<T>.Default,默认情况下默认使用IComparable<T>的{​​{1}}实施,或非T的非IComparable前者不存在。

此代码有效:

public class Program
{
    static void Main(string[] args)
    {
        var list = new List<Stuff>
                       {
                           new Stuff("one"),
                           new Stuff("two"),
                           new Stuff("three"),
                           new Stuff("four")
                       };

        var sorted = list.OrderBy(x => x);

        foreach (var stuff in sorted)
        {
            Console.Out.WriteLine(stuff.Name);
        }
    }
}

public class Stuff : IComparable<Stuff>
{
    public string Name { get; set; }

    public Stuff(string name)
    {
        Name = name;
    }

    public int CompareTo(Stuff other)
    {
        return String.CompareOrdinal(Name, other.Name);
    }
}

答案 1 :(得分:0)

public static class GenericSorter
{
    public static IOrderedEnumerable<T> Sort<T>(IEnumerable<T> toSort, Dictionary<string, SortingOrder> sortOptions)
    {
        IOrderedEnumerable<T> orderedList = null;

        foreach (KeyValuePair<string, SortingOrder> entry in sortOptions)
        {
            if (orderedList != null)
            {
                if (entry.Value == SortingOrder.Ascending)
                {
                    orderedList = orderedList.ApplyOrder<T>(entry.Key, "ThenBy");
                }
                else
                {
                    orderedList = orderedList.ApplyOrder<T>(entry.Key, "ThenByDescending");
                }
            }
            else
            {
                if (entry.Value == SortingOrder.Ascending)
                {
                    orderedList = toSort.ApplyOrder<T>(entry.Key, "OrderBy");
                }
                else
                {
                    orderedList = toSort.ApplyOrder<T>(entry.Key, "OrderByDescending");
                }
            }
        }

        return orderedList;
    }

    private static IOrderedEnumerable<T> ApplyOrder<T>(this IEnumerable<T> source, string property, string methodName)
    {
        ParameterExpression param = Expression.Parameter(typeof(T), "x");
        Expression expr = param;
        foreach (string prop in property.Split('.'))
        {
            expr = Expression.PropertyOrField(expr, prop);
        }
        Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), expr.Type);
        LambdaExpression lambda = Expression.Lambda(delegateType, expr, param);

        MethodInfo mi = typeof(Enumerable).GetMethods().Single(
                method => method.Name == methodName
                        && method.IsGenericMethodDefinition
                        && method.GetGenericArguments().Length == 2
                        && method.GetParameters().Length == 2)
                .MakeGenericMethod(typeof(T), expr.Type);
        return (IOrderedEnumerable<T>)mi.Invoke(null, new object[] { source, lambda.Compile() });
    }
}