2012-10-05 4 views
20

사용자 지정 정렬 비교 자와 특정의 LINQ 표현을위한 두 가지 형식이 있습니다의 LINQ 구문 <T>

형식 1

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

형식이

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

질문 :
두 번째 forma의 order-by 표현식에 대한 구문은 무엇입니까? 티?

아니요 :
첫 번째 형식과 같이 사용자 지정 비교자를 사용하는 방법.

보너스 제공 :
은 위의 두 가지의 LINQ 형식에 대한 실제, 공식적인 이름이 있습니까?

답변

19

두 번째 형식의 표현 -에 의해을 주문에 대한 구문은 무엇이며, 형식 2 "쿼리 구문"입니다 방법 구문입니까?

존재하지 않습니다. orderby clause documentation에서 :

사용자 지정 비교자를 지정할 수도 있습니다. 그러나 메서드 기반 구문을 사용하는 경우에만 사용할 수 있습니다.


어떻게 첫번째 형식에서 사용자 지정 비교자를 사용합니다.

올바르게 작성했습니다. 작성한대로 IComparer<T>을 전달할 수 있습니다.


는 위의 두 가지의 LINQ 형식이 실제 공식 이름 있습니까?

형식 (1) "방법 기반 구문"(from previous link)라고하고, 형식 2 (here에서) "쿼리 식 구문"입니다.

+1

품질 linq 링크! 메소드 기반 구문의 order-by 구문에 대한 설명은 실제로 대답의 일부가 아니었지만 :) –

+1

@SteveKonves 방금 어쨌든 그것을 포함 시켰습니다. 당신은 쉽게 무시할 수 있습니다;) –

2

첫 번째 형식과 같이 사용자 지정 비교기를 사용하는 방법.

해당 형식으로는 사용자 지정 비교기를 사용할 수 없습니다.

위에 나열된 두 개의 Linq 형식에 대한 실제 이름이 있습니까?

형식 1

2

질문 : 불가능 쿼리 구문

그게 더 과부하가 없기 때문입니다.

하지 질문 : 당신은 개체를 비교하기 위해 반사를 사용하는 경우에만

당신은 익명의 유형과 비교자를 사용할 수 있습니다, 그것은 비교하는 형식으로 구현을 사용하는 것이 좋습니다.

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

보너스 신용 : 당신이 유형이 지정된 구현을 만들지 않으려면

당신이 Tuple 사용할 수 있습니다

  • 쿼리 구문이나 이해 구문
  • 방법 구문 또는 확장 메서드 구문
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); 

큰 장점은 다음, 당신은 단지 새로운 람다를 연결할 수 있습니다 경우에 의해 각 주문에 대한 새로운 클래스를 만들 필요가 없다는 것입니다. 분명히 이것은 모든 종류의 방법으로 확장 될 수 있습니다. 그래서 누군가가 어딘가에서 도움이되기를 바랍니다.