Linq: Select 和 Where 有什么不同

在 Linq 中可以使用 SelectWhere方法。关于这两种方法,每个开发人员应该知道些什么?例如: 什么时候用一个比另一个,用一个比另一个有什么好处,等等。

72510 次浏览

选择将可枚举数映射到新结构。如果对 IEnumable 执行选择,则将获得具有相同数量的元素但根据指定的映射类型不同的数组。其中过滤 IEnumable,使其为您提供原始 IEnumable 的子集。

在哪里

查找匹配的项,并只返回匹配的项(过滤)。

- > IEnumerable<A>进,IEnumerable<A>

选择

返回源中 所有项的值(投影/变换)。某些东西可能是项目本身,但通常是某种类型的投影。

- > IEnumerable<A>收,IEnumerable<B>

它们是截然不同的:

Select就是 变形

Where就是 过滤

选择 在哪里是作用于 数不胜数的两个完全不同的运算符。

第一个是 投影操作员,最后一个是 限制操作员

了解这些操作符行为的一个有趣的方法是查看它们的“函数类型”。

  • 它接受包含 T1类型元素的 IEnumable 和将 T1类型元素转换为 T2类型元素的函数作为输入。输出是包含 T2类型元素的 IEnumable。

    由此可以很容易地猜测,这个运算符将通过对输入 IEnumable 的每个元素应用输入函数并将结果封装在一个新的 IEnumable 中来生成其输出。

    使用一些类似数学的符号,它将 (a,b,c,...) : IEnumable < T1 > F: T1 & rarr; T2作为输入并生成 (f (a) ,f (b) ,f (c) ,...) : IEnumable < T2 >

  • 这个函数接受包含 T1类型的元素和 T1上的谓词(即为 T1类型的输入产生布尔结果的函数)的 IEnumable。您可以看到输出也是一个包含 T1类型元素的 IEnumable。

    这一次,根据谓词对元素的应用结果,可以猜测输入 IEnumable 的某个元素将出现在输出 IEnumable 上。为此添加操作符名称的语义,可以确保它只从输入中获取在谓词应用程序上计算为 true 的元素,从而生成输出 IEnumable。

函数式程序设计背景的人通常是这样想的。它允许您仅通过查看运算符的类型来推断(或至少猜测...)运算符的作用!

作为练习,在查看文档之前,请尝试查看 IEnumerables 上的 LINQ 引入的其他操作符,并推断它们的行为!

如果您知道他们如何实现 Where 并选择扩展方法,您就可以预测它正在做什么..。 我试图实现在哪里和选择扩展方法... 你可以看看它..。

实施地点:

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 );
}
}

我的实现对于任何集合都可以很好地工作... ... 但是它不同于微软实现的扩展方法,因为它们使用表达式树来实现相同的功能。

过滤器

地图

两者都返回 IEnumerable<T>

在选择它的情况下,您可以映射到一个新结构的 IEnumable。

  A.Select(x=>new X{UID=x.uid, UNAME=x.uname})
//input as [IEnumerable<A>] -------->  return output as [IEnumerable<X> ]

如果()作为 IEnumable 的过滤器,它将根据 Where 子句返回结果。

A.Where(x=>x.uid!=0) //input as [IEnumerable<A>] -------->  return output as [IEnumerable<A> ]
List<string> randomList = new List<string> { "1", "2", "3" };
var result = test.Where(value => value == "1");
Console.WriteLine(result.Count());

结果将产生“1”,其中包含对象“1”后过滤掉。

List<string> randomList = new List<string> { "1", "2", "3" };
var result = test.Select(value => value == "1");
Console.WriteLine(result.Count());

将产生“3”作为结果,因为它不过滤,即使条件匹配。

结论: 凡检查条件。Select 不关心条件,它将映射所有内容,但关键是,它将只映射您想要映射的内容... (通过 map,它的意思是,如果您愿意,可以读取)。例如,在具有多个变量的类中,select 操作将允许您选择要读取的变量:

class Person
{
public string Name { get;set; }
public int Age { get;set; }
}

然后你就可以拥有:

List<Person> persons = new();
List<string> namePersons = persons.Select(person => person.Name);

它允许您只映射每个人的名称,如果您的列表。

选择也可以实现‘ let’操作(代码相当于链式 LINQ 扩展方法调用中的 let 关键字)的功能

你也可以用它来创建新的对象,以及你想在列表中使用的变量:

  List<Person> persons = new();
var personsWithBlueEyes = persons.Select(person => new { Name=person.Name, Eyes="blue" });

你不得不怀疑:

  1. 我究竟需要从我所拥有的这些价值观中映射出什么?
  2. 我必须应用什么条件来过滤我需要的值(如果确实需要的话) ?

希望这个小屋能照亮