Сведения о вопросе

Oleksandrop

16:03, 1st July, 2020

Теги

c#   linq   .net-3.5   lambda    

Когда использовать метод расширения с lambda над LINQtoObjects для фильтрации коллекции?

Просмотров: 440   Ответов: 4

Я прототипирую некоторые фильтры коллекции 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);

И если я использую метод расширения Where в сочетании с Lambda, фильтр также работает:

var f = MyProducts.Where(mp => mp.Price < 50d).ToList();

Вопрос: в чем разница, и зачем использовать одно над другим?



  Сведения об ответе

park

18:03, 1st July, 2020

LINQ превращается в вызов метода, как у вас есть код.

Другими словами, никакой разницы быть не должно.

Однако в двух ваших фрагментах кода вы не вызываете .ToList в первом, поэтому первый фрагмент кода будет производить перечисляемый источник данных, но если вы вызываете .ToList на нем, то эти два должны быть одинаковыми.


  Сведения об ответе

dumai

18:03, 1st July, 2020

Как уже упоминалось, 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 становится действительно ценным, так это в гораздо более сложных циклах.

Например, этот оператор может включать в себя группы bys, заказы и несколько операторов let и все еще быть читаемым в формате Linq, когда эквивалент .Method().Method.Method() будет усложнен.


  Сведения об ответе

crush

18:03, 1st July, 2020

Синтаксис, который вы используете для d , будет преобразован компилятором в тот же IL, что и методы расширения. Синтаксис "SQL-like" должен быть более естественным способом представления выражения LINQ (хотя лично я предпочитаю методы расширения). Как уже было указано, первый пример вернет результат IEnumerable, а второй пример вернет результат списка из-за вызова ToList(). Если вы удалите вызов ToList() во втором примере, они оба вернут тот же результат, что и Where возвращает результат IEnumerable.


  Сведения об ответе

#hash

18:03, 1st July, 2020

Кроме разницы в ToList, #2 гораздо более удобочитаем и естественен IMO


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться