연결 LINQ 확장 메서드 호출에서 'let'키워드에 해당하는 코드


192

C # 컴파일러 쿼리 이해 기능을 사용하여 다음과 같은 코드를 작성할 수 있습니다.

var names = new string[] { "Dog", "Cat", "Giraffe", "Monkey", "Tortoise" };
var result =
    from animalName in names
    let nameLength = animalName.Length
    where nameLength > 3
    orderby nameLength
    select animalName; 

위의 쿼리 표현식에서 let키워드를 사용하면에 대한 중복 호출없이 where 및 orderby 작업으로 값을 전달할 수 있습니다 animalName.Length.

여기서 "let"키워드의 기능을 수행하는 동등한 LINQ 확장 메서드 호출 집합은 무엇입니까?


11
참고로, C # 3.0 사양은 모든 쿼리 이해 변환 규칙을 매우 상세하게 설명합니다.
Eric Lippert

17
및 사양 무거운가 너무 ;-p 깊이 커버에, 존 소총의 C #을가는 찾을 사람들을위한
마크 Gravell

C # 언어 사양은 검색 엔진에서 콘텐츠를 인덱싱하지 않으며 온라인으로 링크하거나 찾아 볼 수없는 Word 문서를 다운로드 할 수 있습니다. 사양이 온라인으로 제공된다면 큰 도움이 될 것입니다.
Olivier Jacot-Descombes

답변:


250

자체 조작을하지 말자. 피기 백합니다 Select. "반사판"을 사용하여 기존 dll을 분리하면이를 볼 수 있습니다.

그것은 다음 과 같을 것입니다 :

var result = names
        .Select(animalName => new { nameLength = animalName.Length, animalName})
        .Where(x=>x.nameLength > 3)
        .OrderBy(x=>x.nameLength)
        .Select(x=>x.animalName);

4
Woah, 나는 당신이 그런 새로운 연산자를 사용하여 자동 캡슐화 할 수 있다는 것을 몰랐습니다.
David Pfeffer

19
LinqPad의 결과 창에서 작은 "lambda"버튼을 사용하여 Queryable로 시작하는 경우 생성 된 코드를 볼 수도 있습니다. 즉, 첫 줄을 var names = new string [] { "Dog", ...} .AsQueryable (); LinqPad에서 모든 것을 실행하고 작은 람다 버튼을 클릭하면 Marc의 답변과 거의 동일한 생성 코드가 표시됩니다.
Reb. Cabin

3
.Dump()결과 람다를 보려면 LinqPad 에서 확장 메소드 를 사용해야했습니다 .
justanotherdev

88

여기 좋은 기사가 있습니다

기본적 let으로 익명의 튜플을 만듭니다. 다음과 같습니다.

var result = names.Select(
  animal => new { animal = animal, nameLength = animal.Length })
.Where(x => x.nameLength > 3)
.OrderBy(y => y.nameLength)
.Select(z => z.animal);

위의 기사it seems prudent to recommend against using the let keyword in cases where you do not need to transform a variable
JB를

더 인용 :This could be considered a micro-optimisation
Monsignor

7

System.Interactive에는 .Let 확장 방법도 있지만 그 목적은 유창한 식에서 '인라인'으로 평가할 람다 식을 도입하는 것입니다. 예를 들어, LinqPad에서 실행될 때마다 새로운 난수를 생성하는 다음 표현식을 고려하십시오.

var seq = EnumerableEx.Generate(
    new Random(),
    _ => true,
    _ => _,
    x => x.Next());

새로운 랜덤 샘플이 매번 나타나는지 확인하려면 다음을 고려하십시오.

seq.Zip(seq, Tuple.Create).Take(3).Dump();

왼쪽과 오른쪽이 다른 쌍을 생성합니다. 왼쪽과 오른쪽이 항상 같은 쌍을 만들려면 다음과 같이하십시오.

seq.Take(3).ToList().Let(xs => xs.Zip(xs, Tuple.Create)).Dump(); 

람다 식을 직접 호출 할 수 있다면

(xs => xs.Zip(xs, Tuple.Create))(seq.Take(3).ToList()).Dump();

그러나 람다 식은 마치 메서드 인 것처럼 호출 할 수 없습니다.


1

대한 '하자'키워드에 체인 된 LINQ 확장 메서드 호출에 해당하는 코드

위의 의견은 더 이상 유효하지 않습니다

var x = new List<int> { 2, 3, 4, 5, 6 }.AsQueryable();
(from val in x
let val1 = val
let val2 = val + 1
where val2 > val1
select val
).Dump();

생산

System.Collections.Generic.List`1[System.Int32]
.Select(
  val =>
     new
     {
         val = val,
         val1 = val
     }
)
.Select(
  temp0 =>
     new
     {
         temp0 = temp0,
         val2 = (temp0.val + 1)
     }
)
.Where(temp1 => (temp1.val2 > temp1.temp0.val1))
.Select(temp1 => temp1.temp0.val)

let이제 여러 개가 최적화되었습니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.