Linq:Select和Where和有什么区别


122

SelectWhereLinq中的方法可用。每个开发人员应该对这两种方法了解什么?例如:何时使用另一种,使用另一种的优势等等。


7
我认为这个问题不应标记为CW,它可能会有明确的答案。
布兰登

1
@Brandon标记目标对象是正确的,这没有错。
Rex M

@雷克斯,我同意。只是说Select和Where之间的区别有明确的答案,问题的第二部分很可能基于公认的惯例。我只是指出是为了防止OP不确定将其标记为CW。如果他确实打算成为CW,那么我可以罚款。
布兰登

6
这有很多错。CW毫无用处,当人们完全随机地将问题标记为CW时,CW变得越来越无用了
jalf

Answers:


126

哪里

查找匹配的项目,仅返回匹配的项目(过滤)。

- > IEnumerable<A>中,IEnumerable<A>

选择

返回源中所有项目的某些内容(投影/转换)。这些东西可能是物品本身,但通常更是某种形式的投影。

- > IEnumerable<A>中,IEnumerable<B>


15
Select将始终返回列表中相同数量的元素(无论您可能具有哪种过滤条件)。 Where可以根据您的过滤条件返回较少的元素。
goku_da_master

这里是一个MSDN例子select这里是一个where
yazanpro

至少对我来说,与其他语言有一定的背景,这有助于思考Where == filterSelect == map
bgusach

52

SelectWhere是作用于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上,这取决于谓词对该元素的应用结果。通过添加运算符名称的语义,可以确保通过将输入中的那些仅在谓词应用中计算为true的元素从输入中取出,从而确保它会生成输出IEnumerable。

具有函数式编程背景的人们通常会这样认为。它允许您仅通过查看操作符的类型来推断(或至少可以猜测...)!

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



18

Select将可枚举映射到新结构。如果对IEnumerable执行选择,则将获得具有相同数量元素但不同类型的数组,具体取决于指定的映射。在其中过滤IEnumerable,以便为您提供原始IEnumerable的子集。



7

如果您知道他们是如何实现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 );
    }
}

我的实现对于任何集合都可以正常工作...但是它不同于Microsoft实现的扩展方法,因为它们使用表达式树来实现相同的方法。


1

如果选择“选择”,则可以映射到新结构的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> ]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.