2012-08-09 67 views
1

我有一个类型,它具有默认排序顺序,因为它实现了IComparable<T>IComparable。我没有得到我期望从LINQ得到的结果,基本上看起来好像IComparable<T>类型实现的没有被应用。如何在Linq OrderBy子句中应用默认IComparable <T>

我想我会得到我想要与形式的表达式的结果:

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

其中T本身实现IComparable<T>。这没有发生。

我能看到具体IComparable<T>类用于排序指定相关的问题,但我不能找到一个使用由T本身实现的默认IComparable<T>

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

在此先感谢。

+0

你不应该继承IEquatable的LINQ? – Manatherin 2012-08-09 09:46:05

+0

请发布您的'IComparable '执行。 – Ani 2012-08-09 10:19:39

+0

欢迎来到SO,Mike。我根据[常见问题](http://stackoverflow.com/faq)从问题中删除了您的姓名。如果“Mike”确实是你的名字,你可能想在[你的个人资料](http://stackoverflow.com/users/1587065)中使用它,而不是无聊的_user1587065_。 – 2012-08-09 11:36:10

回答

2

OrderBy使用默认的比较Comparer<T>.Default这反过来会默认使用IComparable<T>实施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); 
    } 
} 
+0

感谢您迅速回应Christoffer。我对IComparable&lt; T>实现感到满意:我已经使用List&ltT> .Sort()方法对其进行了检查。如果序列是一个List < T>,它实现了一个Sort()方法吗?是否有区别?我的完整语法,我现在意识到我应该写完整的,对不起! )是: var result = someQueryable .Where(x => x.Property == value).OrderBy(r => r); 在调用OrderBy(r => r)之前,我没有实现查询结果(例如使用ToList())。 – Mike 2012-08-13 08:13:52

+0

@Mike'IEnumerable .OrderBy(r => r)'和'List .Sort()'之间的排序没有区别。他们都使用默认比较器“比较器。默认”。不同之处在于'.Sort()'重新排列了'List '的元素,而'.OrderBy(...)'没有。 – 2012-08-13 08:45:06

+0

@Mike你是否需要更多的帮助解决这个问题,还是解决了?如果您对答案不满意,请随时发表评论。另一方面,如果您对答案感到满意,请将答案标记为已接受。谢谢。 – 2012-08-15 15:28:44

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() }); 
    } 
}