이런 식으로 쓰면 :
var things = mythings
.Where(x => x.IsSomeValue)
.Where(y => y.IsSomeOtherValue)
이것은 다음과 같습니다.
var results1 = new List<Thing>();
foreach(var t in mythings)
if(t.IsSomeValue)
results1.Add(t);
var results2 = new List<Thing>();
foreach(var t in results1)
if(t.IsSomeOtherValue)
results2.Add(t);
또는 다음과 같이 작동하는 표지 아래에 마술이 있습니까?
var results = new List<Thing>();
foreach(var t in mythings)
if(t.IsSomeValue && t.IsSomeOtherValue)
results.Add(t);
아니면 완전히 다른 것입니까?
답변
LINQ 쿼리는 지연 됩니다. 그것은 코드를 의미합니다 :
var things = mythings
.Where(x => x.IsSomeValue)
.Where(y => y.IsSomeOtherValue);
거의하지 않습니다. 원래 열거 형 ( mythings
)은 결과 열거 형 ( things
)이 예를 들어 foreach
루프 .ToList()
, 또는로 소비 될 때만 열거됩니다 .ToArray()
.
를 호출하면 things.ToList()
후자의 코드와 대략 동일하며 열거 자에서 약간의 (일반적으로 중요하지 않은) 오버 헤드가 있습니다.
마찬가지로 foreach 루프를 사용하는 경우 :
foreach (var t in things)
DoSomething(t);
성능면에서 다음과 유사합니다.
foreach (var t in mythings)
if (t.IsSomeValue && t.IsSomeOtherValue)
DoSomething(t);
열거 형에 대한 게으름 접근 방식의 성능 이점 중 일부는 (모든 결과를 계산하고 목록에 저장하는 것과는 대조적으로) 메모리를 거의 사용하지 않으며 (한 번에 하나의 결과 만 저장되므로) 중요한 것은 없습니다 초기 비용.
열거 형이 부분적으로 만 열거되는 경우 특히 중요합니다. 이 코드를 고려하십시오.
things.First();
LINQ가 구현되는 방식은 mythings
위치 조건과 일치하는 첫 번째 요소까지만 열거됩니다. 해당 요소가 목록에서 일찍 나오는 경우 성능이 크게 향상 될 수 있습니다 (예 : O (n) 대신 O (1)).
답변
다음 코드 :
var things = mythings
.Where(x => x.IsSomeValue)
.Where(y => y.IsSomeOtherValue);
게으른 평가로 인해 아무것도 발생하지 않습니다.
var things = mythings
.Where(x => x.IsSomeValue)
.Where(y => y.IsSomeOtherValue)
.ToList();
평가가 시작되기 때문에 다릅니다.
의 각 항목은 mythings
첫 번째에 제공 Where
됩니다. 통과하면 두 번째에 제공 Where
됩니다. 통과하면 출력의 일부가됩니다.
그래서 이것은 다음과 같이 보입니다 :
var results = new List<Thing>();
foreach(var t in mythings)
{
if(t.IsSomeValue)
{
if(t.IsSomeOtherValue)
{
results.Add(t);
}
}
}
답변
지연 된 실행은 제쳐두고 (다른 답변은 이미 설명했지만 다른 세부 사항을 지적하겠습니다) 두 번째 예와 비슷합니다.
그냥 당신이 전화를 가정 해 봅시다 ToList
에 things
.
의 구현 Enumerable.Where
은를 반환합니다 Enumerable.WhereListIterator
. 당신이 호출하면 Where
그에 WhereListIterator
(일명 체인 Where
, 당신은 더 이상 전화 -calls) Enumerable.Where
하지만, Enumerable.WhereListIterator.Where
실제로 조건을 결합, (사용 Enumerable.CombinePredicates
).
그래서 더 비슷 if(t.IsSomeValue && t.IsSomeOtherValue)
합니다.
답변
아니요 동일하지 않습니다. 당신의 예에서 things
인 IEnumerable
이 시점에서 여전히 반복자가 아닌 실제 배열이나리스트이다. 또한 things
사용되지 않으므로 루프는 평가되지 않습니다. 이 유형을 IEnumerable
사용하면 yield
Linq 명령어에 의해 -ed 요소를 반복 하고 더 많은 명령어로 더 처리 할 수 있습니다. 결국에는 실제로 하나의 루프 만 있습니다.
그러나 즉시로 같은 명령을 추가 .ToArray()
하거나 .ToList()
당신이 따라서, 실제 데이터 구조의 생성을 주문하여 체인에 경계를두고있어.
이 관련 SO 질문을 참조하십시오 : https : //.com/questions/2789389/how-do-i-implement-ienumerable