LINQ 표현식을 번역 할 때 C# 컴파일러가 SelectMany를 어떻게 선택합니까?

StackOverflow https://stackoverflow.com/questions/422958

  •  05-07-2019
  •  | 
  •  

문제

enumerable.selectmany에는 4 개의 과부하 서명이 있습니다. 간단하게하기 위해 두 서명을 무시합니다. int 논쟁. 따라서 SelectMany에 대한 2 개의 서명이 있습니다.

public static IEnumerable<TResult> SelectMany<TSource, TResult>(
    this IEnumerable<TSource> source,
    Func<TSource, IEnumerable<TResult>> selector
)

public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(
    this IEnumerable<TSource> source,
    Func<TSource, IEnumerable<TCollection>> collectionSelector,
    Func<TSource, TCollection, TResult> resultSelector
)

내 질문은 : C# 컴파일러가 LINQ 표현식을 확장 메소드로 변환 할 때 SelectMany를 선택하는 방법은 무엇입니까?

기본적으로 여러 가지가있는 경우 ~에서 LINQ 표현에는 SelectMany가 있습니다. 그러나 C# 컴파일러는 두 번째 서명 만 선택하는 것 같습니다. 첫 번째 서명은 사용되지 않습니다.

        IEnumerable<int> en1 = Enumerable.Range(1, 3);
        IEnumerable<double> en2 = new double[] { 1.0, 3.14 };

        IEnumerable<string> en3 =
            from i1 in en1
            from i2 in en2
            select (i1 * i2).ToString();

        foreach (var i in en3)
        {
            Console.WriteLine(i);
        }

반사기의 도움으로 위의 LINQ 표현이

en1.SelectMany<int, double, string>(delegate (int i1) {
        return en2;
    }, delegate (int i1, double i2) {
        double CS$0$0000 = i1 * i2return CS$0$0000.ToString();
    })

위의 예에는 3 가지 유형이 포함됩니다. 따라서 두 번째 SelectMany 서명을 선택하는 것이 합리적입니다. 그러나 아래의 예를 들어, 하나의 유형 만 관련되어 있지만 여전히 두 번째 서명을 선택합니다.

        IEnumerable<int> en4 =
            from i1 in en1
            from i2 in Enumerable.Range(0, i1)
            select i2;

다음으로 번역됩니다.

en1.SelectMany<int, int, int>(delegate (int i1) {
        return Enumerable.Range(0, i1);
    }, delegate (int i1, int i2) {
        return i2;
    })

따라서 LINQ 표현이 첫 번째 SelectMany 서명으로 변환 된 사례를 찾을 수 없습니다. 그런 경우가 있습니까?

첫 번째 SelectMany 서명이 사용되지 않으면 기능 프로그래밍에서 Monad의 바인드이기 때문에 존재합니까?

아마도 질문은 다음과 같습니다. 왜 우리는 SelectMany의 2 개의 서명이 있습니까?

감사.

도움이 되었습니까?

해결책

C# 사양에 따르면 컴파일러는 SelectMany의 첫 번째 버전에 과부하 호출을 생성하지 않습니다. SelectMany의 첫 번째 버전은 목록 목록을 단일 플랫 목록으로 평평하게하는 데 유용합니다.

public IEnumerable<string> Example(IEnumerable<IEnumerable<string>> enumerable) {
  return enumerable.SelectMany(x => x);
}

쿼리 표현식에는 강력한 동등이 없습니다.

자세한 내용은 C# 언어 사양의 7.15.2 절을 참조하십시오.

다른 팁

SelectMany의 2 개의 서명이있는 이유는 무엇입니까?

그래서 내 코드에서 첫 번째를 사용할 수 있습니다.

var orders = Customers.SelectMany(c => c.Orders)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top