2012-10-05 12 views
20

カスタムの並べ替え比較子を持つ任意のLINQの式のための2つの形式がありますLINQの構文<T>

フォーマット1

var query = 
    source 
    .Select(x => new { x.someProperty, x.otherProperty }) 
    .OrderBy(x => x, new myComparer()); 

フォーマット2

var query = 
    from x in source 
    orderby x // comparer expression goes here? 
    select new { x.someProperty, x.otherProperty }; 

質問:
2番目の形式の発注式の構文は次のとおりですt?

ご不明な点:
最初の形式のようにカスタムコンペアを使用する方法。

ボーナスクレジット:
は、上記の2つのLINQのフォーマットの実際、正式な名前はありますか?

答えて

19

二形式の式-順の構文は何で、フォーマット2は、「クエリ構文」で、メソッドの構文ですか?

存在しません。 orderby clause documentationから:

カスタムコンペアラを指定することもできます。ただし、メソッドベースの構文を使用してのみ使用できます。第1のフォーマットでカスタムの比較子を使用する方法


正しく書きました。あなたが書いた通りにIComparer<T>を渡すことができます。


上記の2つのLINQのフォーマットの実際、正式な名前はありますか?

フォーマット1 "法による構文"(from previous link)と呼ばれ、フォーマット2(hereから) "クエリ式の構文" です。

+1

品質のlinqリンク!メソッドに基づく構文のorder-by構文に関する記述は実際には答えの一部ではないと考えられましたが、 :) –

+1

@SteveKonves私はちょうどそれをとにかく含めた。あなたは簡単に無視することができます;) –

2

最初の形式で示したようにカスタムコンペアを使用する方法。

この形式では、カスタムコンペアは使用できません。

上記の2つのLinq形式の実際の正式な名前はありますか?

フォーマット1は

2

質問:何のオーバーロードがないため

は、クエリ構文では可能ではない厥。

ない質問:あなたがオブジェクトを比較するためにリフレクションを使用する場合にのみ

あなたは匿名型との比較演算子を使用することができ、それは比較のために型指定された実装を使用することをお勧めします。

あなたがTupleを使用することができます入力された実装を作成したくない場合は、次の

var query = 
    source 
    .Select(x => new Tuple<string, int>(x.someProperty, x.otherProperty)) 
    .OrderBy(x => x, new MyComparer()); 

public class MyComparer : IComparer<Tuple<string, int>> 
{ 
    public int Compare(Tuple<string, int> x, Tuple<string, int> y) 
    { 
    return x.Item1.CompareTo(y.Item1); 
    } 
} 

ボーナスクレジット:

  • クエリ構文や読解構文
  • メソッドの構文または拡張メソッド構文
2

これは必ずしも元の質問に答えるものではありませんが、概説されている可能性のいくつかを幾分拡張します。他の人が同様の問題を抱えている場合に備えて私はこれを投稿しています。 ここに掲載されたソリューションは、他の場合に有用なオプション別の一般的な注文を概説しています。この例では、さまざまなプロパティでファイルリストを並べ替える必要がありました。実装に続いて

/// <summary> 
/// Used to create custom comparers on the fly 
/// </summary> 
/// <typeparam name="T"></typeparam> 
public class GenericCompare<T> : IComparer<T> 
{ 
    // Function use to perform the compare 
    private Func<T, T, int> ComparerFunction { set; get; } 

    // Constructor 
    public GenericCompare(Func<T, T, int> comparerFunction) 
    { 
     ComparerFunction = comparerFunction; 
    } 

    // Execute the compare 
    public int Compare(T x, T y) 
    { 

     if (x == null || y == null) 
     { 
      // These 3 are bell and whistles to handle cases where one of the two is null, to sort to top or bottom respectivly 
      if (y == null && x == null) { return 0; } 
      if (y == null) { return 1; } 
      if (x == null) { return -1; } 
     } 

     try 
     { 
      // Do the actual compare 
      return ComparerFunction(x, y); 
     } 
     catch (Exception ex) 
     { 
      // But muffle any errors 
      System.Diagnostics.Debug.WriteLine(ex); 
     } 

     // Oh crud, we shouldn't be here, but just in case we got an exception. 
     return 0; 
    } 
} 

...

 GenericCompare<FileInfo> DefaultComparer; 

     if (SortOrder == SORT_FOLDER_FILE) 
     { 
      DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) => 
      { 
       return fr1.FullName.ToLower().CompareTo(fr2.FullName.ToLower()); 
      }); 
     } 
     else if (SortOrder == SORT_SIZE_ASC) 
     { 
      DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) => 
      { 
       return fr1.Length.CompareTo(fr2.Length); 
      }); 
     } 
     else if (SortOrder == SORT_SIZE_DESC) 
     { 
      DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) => 
      { 
       return fr2.Length.CompareTo(fr1.Length); 
      }); 
     } 
     else 
     { 
      DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) => 
      { 
       return fr1.Name.ToLower().CompareTo(fr2.Name.ToLower()); 
      }); 
     } 

     var ordered_results = (new DirectoryInfo(@"C:\Temp")) 
       .GetFiles() 
       .OrderBy(fi => fi, DefaultComparer); 

大きな利点は、あなたが、あなただけの新しいラムダを配線することができます場合によって各注文の新しいクラスを作成する必要がないことです。明らかに、これはさまざまな方法で拡張することができるので、うまくいけば誰かがいつかどこかで助けになるでしょう。