Когда использовать метод расширения с лямбдой над LINQtoObjects для фильтрации коллекции?
Я создаю прототипы некоторых фильтров коллекции С# 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);
И если я использую метод расширения Where, объединенный с Lambda, фильтр также работает:
var f = MyProducts.Where(mp => mp.Price < 50d).ToList();
Вопрос: В чем разница и зачем использовать один над другим?
Ответы
Ответ 1
LINQ превращается в вызовы методов, такие как код, который у вас есть.
Другими словами, не должно быть разницы.
Однако в ваших двух частях кода вы не вызываете .ToList в первом, поэтому первый фрагмент кода будет генерировать перечислимый источник данных, но если вы вызываете .ToList на нем, то они должны быть одинаковыми.
Ответ 2
Как упоминалось, d будет IEnumerable<MyProduct>
, а f - List<MyProduct>
Преобразование выполняется компилятором С#
var d =
from mp in MyProducts
where mp.Price < 50d
select mp;
Преобразуется в (до компиляции в IL и с расширением generics):
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 становится действительно ценным, он находится в гораздо более сложных циклах.
Например, это утверждение может включать в себя группировки, заказы и несколько утверждений let и все еще быть читаемыми в формате Linq, когда эквивалентный .Method().Method.Method()
будет усложняться.
Ответ 3
Помимо отличия ToList, # 2 является более читаемым и естественным IMO
Ответ 4
Синтаксис, который вы используете для d, преобразуется компилятором в тот же IL, что и методы расширения. Предполагается, что синтаксис "SQL-like" является более естественным способом представления выражения LINQ (хотя я лично предпочитаю методы расширения). Как уже отмечалось, первый пример возвращает результат IEnumerable, а второй пример возвращает результат List из-за вызова ToList(). Если во втором примере вы удалите вызов ToList(), они оба возвратят тот же результат, что и Where, возвращает результат IEnumerable.