Select
И Where
методы доступны в Linq. Что каждый разработчик должен знать об этих двух методах? Например: когда использовать одно над другим, какие преимущества от использования одного над другим и т. Д.
Select
И Where
методы доступны в Linq. Что каждый разработчик должен знать об этих двух методах? Например: когда использовать одно над другим, какие преимущества от использования одного над другим и т. Д.
Ответы:
куда
находит совпадающие элементы и возвращает только те, которые соответствуют ( фильтрация ).
-> IEnumerable<A>
внутрь, IEnumerable<A>
наружу
Выбрать
возвращает что-то для всех элементов в источнике ( проекция / преобразование ). Это что-то может быть самими предметами, но чаще всего это своего рода проекция.
-> IEnumerable<A>
внутрь, IEnumerable<B>
наружу
Select
всегда будет возвращать одинаковое количество элементов в списке (независимо от условий фильтрации, которые у вас могут быть). Where
может возвращать меньше элементов в зависимости от условий вашего фильтра.
Where == filter
иSelect == map
Select и Where - два совершенно разных оператора, действующих на IEnumerable .
Первый - это то, что мы называем оператором проекции , а последний - оператор ограничения .
Один интересный способ понять поведение таких операторов - взглянуть на их «функциональный тип».
Выберите: (IEnumerable <T1>, Func <T1, T2>) → IEnumerable <T2> ; на вход он принимает как IEnumerable, содержащий элементы типа T1, так и функцию, преобразующую элементы типа T1 в элементы типа T2. Результатом является IEnumerable, содержащий элементы типа T2.
Исходя из этого, легко догадаться, что этот оператор будет производить свой вывод, применяя функцию ввода к каждому элементу входного IEnumerable и помещая результаты в новый IEnumerable.
Используя некоторые математические обозначения, он принимает в качестве входных данных (a, b, c, ...): IEnumerable <T1> и f: T1 → T2 и производит (f (a), f (b), f (c) , ...): IEnumerable <T2>
Где: (IEnumerable <T1>, Func <T1, bool>) → IEnumerable <T1> ; этот принимает IEnumerable, содержащий элементы типа T1 и предикат на T1 (то есть функцию, которая производит логический результат для ввода типа T1). Вы видите, что вывод также является IEnumerable, содержащим элементы типа T1.
На этот раз можно было бы предположить, что элемент входного IEnumerable будет присутствовать в выходном IEnumerable в зависимости от результата применения предиката к элементу. Добавляя к этому семантику имени оператора, вы можете быть уверены, что он создаст выходной IEnumerable, взяв из входного только те элементы, которые оцениваются как истинные при применении предиката.
Люди с опытом функционального программирования обычно так думают. Это позволяет вам вывести (или хотя бы догадаться ...), что делает оператор, только взглянув на его тип!
В качестве упражнения попробуйте взглянуть на другие операторы, представленные LINQ в IEnumerables, и вывести их поведение, прежде чем просматривать документацию!
Они различны:
Select
все о трансформации .
Where
все о фильтрации .
Select отображает перечислимый объект в новую структуру. Если вы выполните выбор в IEnumerable, вы получите массив с тем же количеством элементов, но другого типа в зависимости от указанного вами сопоставления. Где фильтрует IEnumerable, чтобы получить подмножество исходного IEnumerable.
Where
~ = Фильтр
Select
~ = Карта
Оба возвращения IEnumerable<T>
Если вы знаете, как они реализовали методы расширения Where и select, вы можете предсказать, что он делает ... Я попытался реализовать где и выбрать методы расширения ... Вы можете взглянуть на это ...
Где реализация:
public static IEnumerable<Tsource> Where<Tsource> ( this IEnumerable<Tsource> a , Func<Tsource , bool> Method )
{
foreach ( var data in a )
{
//If the lambda Expression(delegate) returns "true" Then return the Data. (use 'yield' for deferred return)
if ( Method.Invoke ( data ) )
{
yield return data;
}
}
}
Выберите реализацию ::
public static IEnumerable<TResult> Select<TSource , TResult> ( this IEnumerable<TSource> a , Func<TSource , TResult> Method )
{
foreach ( var item in a )
{
//Each iteration call the delegate and return the Data back.(use 'yield' for deferred return)
yield return Method.Invoke ( item );
}
}
Моя реализация отлично работает для любой коллекции ... Но она отличается от методов расширения, реализованных Microsoft, потому что они используют деревья выражений для реализации того же.
В случае Select вы можете сопоставить IEnumerable новой структуры.
A.Select(x=>new X{UID=x.uid, UNAME=x.uname})
//input as [IEnumerable<A>] --------> return output as [IEnumerable<X> ]
Where () работает как фильтр для IEnumerable, он вернет результат на основе предложения where.
A.Where(x=>x.uid!=0) //input as [IEnumerable<A>] --------> return output as [IEnumerable<A> ]