컬렉션을 필터링하기 위해 LINQtoObjects를 통해 람다와 함께 확장 메서드를 사용해야 하는 경우는 언제인가요?
문제
일부 C# 3 컬렉션 필터의 프로토타입을 작성 중인데 이 문제를 발견했습니다.다음과 같은 제품 컬렉션이 있습니다.
public class MyProduct
{
public string Name { get; set; }
public Double Price { get; set; }
public string Description { get; set; }
}
var MyProducts = new List<MyProduct>
{
new MyProduct
{
Name = "Surfboard",
Price = 144.99,
Description = "Most important thing you will ever own."
},
new MyProduct
{
Name = "Leash",
Price = 29.28,
Description = "Keep important things close to you."
}
,
new MyProduct
{
Name = "Sun Screen",
Price = 15.88,
Description = "1000 SPF! Who Could ask for more?"
}
};
이제 LINQ를 사용하여 필터링하면 예상대로 작동합니다.
var d = (from mp in MyProducts
where mp.Price < 50d
select mp);
그리고 Lambda와 결합된 Where 확장 메서드를 사용하면 필터도 작동합니다.
var f = MyProducts.Where(mp => mp.Price < 50d).ToList();
질문: 차이점은 무엇이며 왜 다른 것을 사용합니까?
해결책
LINQ는 사용자가 가지고 있는 코드와 같은 메서드 호출로 전환됩니다.
즉, 차이가 없어야 합니다.
그러나 두 코드 조각에서 처음에는 .ToList를 호출하지 않으므로 첫 번째 코드 조각은 열거 가능한 데이터 소스를 생성하지만 .ToList를 호출하면 두 코드가 동일해야 합니다.
다른 팁
언급했듯이 d는 IEnumerable<MyProduct>
f는 동안 List<MyProduct>
변환은 C# 컴파일러에 의해 수행됩니다.
var d =
from mp in MyProducts
where mp.Price < 50d
select mp;
다음으로 변환됩니다(IL로 컴파일하기 전 및 제네릭이 확장됨).
var d =
MyProducts.
Where<MyProduct>( mp => mp.Price < 50d ).
Select<MyProduct>( mp => mp );
//note that this last select is optimised out if it makes no change
이 간단한 경우에는 차이가 거의 없습니다.Linq가 정말 가치 있는 곳은 훨씬 더 복잡한 루프입니다.
예를 들어 이 문에는 group-bys, 주문 및 몇 가지 let 문이 포함될 수 있으며 동등한 경우 Linq 형식으로 계속 읽을 수 있습니다. .Method().Method.Method()
복잡해질 것입니다.
ToList 차이점 외에 #2는 훨씬 더 읽기 쉽고 자연스러운 IMO입니다.
사용중인 구문 디 컴파일러에 의해 확장 메서드와 동일한 IL로 변환됩니다."SQL과 유사한" 구문은 LINQ 식을 표현하는 더 자연스러운 방법이라고 생각됩니다(개인적으로는 확장 방법을 선호하지만).이미 지적했듯이 첫 번째 예제는 IEnumerable 결과를 반환하는 반면 두 번째 예제는 ToList() 호출로 인해 List 결과를 반환합니다.두 번째 예에서 ToList() 호출을 제거하면 둘 다 Where 반환 an IEnumerable 결과와 동일한 결과를 반환합니다.