2012-08-09 63 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() }); 
    } 
}