Select and Where are two completely different operators acting on IEnumerables.
The first one is what we call a Projection Operator, while the last one is a Restriction Operator. One interesting way to have insight on the behavior of such operators is to take a look at their "functional type".
Select : (IEnumerable, Func<T1,T2>) → IEnumerable; it takes as input both an IEnumerable containing elements of type T1 and a function transforming elements of type T1 into elements of type T2. The output is an IEnumerable containing elements of type T2.
From this, one can easily guess that this operator will produce its output by applying the input function on each element of the input IEnumerable, and wrapping the results inside a new IEnumerable. Using some math-like notation, it takes as input (a, b, c, ...) : IEnumerable and f : T1 → T2 and produces (f(a), f(b), f(c), ...) : IEnumerable
Where : (IEnumerable, Func<T1, bool>) → IEnumerable ; this one takes an IEnumerable containing elements of type T1 and a predicate on T1 (that is, a function that produces a boolean result for an input of type T1). You see that the output is also an IEnumerable containing elements of type T1.
This time one would guess that an element of the input IEnumerable will be present on the output IEnumerable depending on the result of the application of the predicate to the element. Adding to this the semantics of the operator name, you can be sure that it will produce the output IEnumerable by taking from the input one only those elements that evaluates to true on the application of the predicate. People with functional programming background usually think like this. It allows you to deduce (or at least guess...) what an operator does only by looking at it's type! As an exercise, try to look at other operators introduced by LINQ on IEnumerables and deduce their behavior, before looking at the documentation!
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 );
}
}
List<string> randomList = new List<string> { "1", "2", "3" };
var result = test.Where(value => value == "1");
Console.WriteLine(result.Count());
Will produce "1" as result, the one that contains the object "1" after filtering out.
List<string> randomList = new List<string> { "1", "2", "3" };
var result = test.Select(value => value == "1");
Console.WriteLine(result.Count());
Will produce "3" as result, as it doesn't filter, even if the condition match up. Conclusion: Where checks conditions. Select doesn't care a s*** about conditions, it will map everything, but the point is, it will map only what you want to map exactly... (by map, it means, to read, if you prefer). For instance, in an class with multiple variables, the select operation will allow you to choose which one you want to read:
class Person
{
public string Name { get;set; }
public int Age { get;set; }
}
Which allow you to map only the Name of each person if your list. Select can implement the functionality also of 'let' operation ( Code equivalent to the 'let' keyword in chained LINQ extension method calls ) And you can use it also for creating new objects, with the variables you want to use in the list you read:
List<Person> persons = new();
var personsWithBlueEyes = persons.Select(person => new { Name=person.Name, Eyes="blue" });
You have to wonder:
What on earth I need to map from all of these values I have?
What conditions I have to apply to filter only the values I need to (if needed indeed)? Hope this shed light
8条答案
按热度按时间uxhixvfz1#
"在哪里"
查找匹配的项目并仅返回匹配的项目(过滤)。
IEnumerable<A>
输入,IEnumerable<A>
输出选择
返回源中 * 所有 * 项的值(projection / transformation)。该值可能是项本身,但通常是某种类型的投影。
IEnumerable<A>
输入,IEnumerable<B>
输出iibxawm42#
它们是不同的:
Select
都是关于转型。Where
是关于过滤的。yws3nbqq3#
Select and Where are two completely different operators acting on IEnumerables.
The first one is what we call a Projection Operator, while the last one is a Restriction Operator.
One interesting way to have insight on the behavior of such operators is to take a look at their "functional type".
From this, one can easily guess that this operator will produce its output by applying the input function on each element of the input IEnumerable, and wrapping the results inside a new IEnumerable.
Using some math-like notation, it takes as input (a, b, c, ...) : IEnumerable and f : T1 → T2 and produces (f(a), f(b), f(c), ...) : IEnumerable
This time one would guess that an element of the input IEnumerable will be present on the output IEnumerable depending on the result of the application of the predicate to the element. Adding to this the semantics of the operator name, you can be sure that it will produce the output IEnumerable by taking from the input one only those elements that evaluates to true on the application of the predicate.
People with functional programming background usually think like this. It allows you to deduce (or at least guess...) what an operator does only by looking at it's type!
As an exercise, try to look at other operators introduced by LINQ on IEnumerables and deduce their behavior, before looking at the documentation!
np8igboo4#
Where
~=过滤器Select
~=Map两者都返回
IEnumerable<T>
2vuwiymt5#
Select将可枚举对象Map到新结构。如果对IEnumerable执行Select,则将获得一个具有相同元素数但类型不同的数组,具体取决于您指定的Map。Where筛选IEnumerable,以便它为您提供原始IEnumerable的子集。
3bygqnnd6#
如果你知道他们是如何实现Where和select扩展方法的,你就可以预测它在做什么......我试着实现了Where和select扩展方法......你可以看一下......
其中实施:
选择实现::
我的实现对任何集合都能很好地工作...但它与微软实现的扩展方法不同,因为它们使用表达式树来实现相同的方法。
xyhw6mcr7#
Will produce "1" as result, the one that contains the object "1" after filtering out.
Will produce "3" as result, as it doesn't filter, even if the condition match up.
Conclusion: Where checks conditions. Select doesn't care a s*** about conditions, it will map everything, but the point is, it will map only what you want to map exactly... (by map, it means, to read, if you prefer). For instance, in an class with multiple variables, the select operation will allow you to choose which one you want to read:
and then you can have:
Which allow you to map only the Name of each person if your list.
Select can implement the functionality also of 'let' operation ( Code equivalent to the 'let' keyword in chained LINQ extension method calls )
And you can use it also for creating new objects, with the variables you want to use in the list you read:
You have to wonder:
Hope this shed light
yhxst69z8#
如果选择它,则可以Map到新结构的IEnumerable。
Where()用作IEnumerable的过滤器,它将根据where子句返回结果。