LINQ中的“哪里”和“选择”如何工作?

时间:2019-12-06 06:47:20

标签: c# linq

我有以下代码段。我对它后面提到的代码段有很少的疑问。

var salaries = customerList
                    .Where(c => c.Age > 30)
                    .Select(c => c.Salary) // salary is of type long
                    .ToList();
  • 在上面的代码片段中,“哪里”如何访问customerList以及如何定义“ c”的类型?
  • 在应用“选择”操作的过滤器之后,“哪里”会返回临时客户列表吗?
  • “选择”究竟如何知道它只返回“薪水”?
  • 如何将变量“ salaries”的类型设置为List

5 个答案:

答案 0 :(得分:5)

Where可能是这样实现的(请注意,这是一个非常粗糙的实现,请您大致了解一下它的样子):

public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
    foreach (T t in source) {
        if (predicate(t)) {
            yield return t;
        }
    }
}

请注意,Where是扩展方法。您实际上是在呼叫Where(customerList, c => c.Age > 30)。现在,您应该看到它可以访问customerList的位置。它还通过查看T IEnumerable是哪种类型来推断customerList应该是什么。由于它是IEnumerable<Customer>,所以TCustomer,因此它期望第二个参数使用Func<Customer, bool>。这样便知道cCustomer

Where不返回临时列表。许多LINQ方法都使用延迟评估。 Where返回经过过滤的IEnumerable<Customer>。请记住,IEnumerable只是一系列事物。但是,Where返回的此序列直到您要求时才被评估。 Select的作用也一样。因此,只有您调用ToList才会创建列表。

您的第三个问题有点像问“ Where如何知道如何过滤”或“ Console.WriteLine如何知道如何写入屏幕”。 Select就是这样做的。您可以根据需要查看其实现。这是一个粗略的草图:

public static IEnumerable<U> Select<T, U>(this IEnumerable<T> source, Func<T, U> mapping) {
    foreach (T t in source) {
        yield mapping(t);
    }
}

变量salaries的类型是通过查看所调用的每个方法的方法签名来确定的。您的Select调用返回一个IEnumerable<long>,并且ToList的签名告诉编译器,给定一个IEnumerable<T>它将返回List<T>,因此在这种情况下,它返回一个List<long>

答案 1 :(得分:1)

Enumerable类中存在where子句,用于在.net框架中进行查询。它提供布尔条件和返回源。最终它将转换为相应的sql查询。

所以你的linq

var salaries = customerList
                    .Where(c => c.Age > 30)
                    .Select(c => c.Salary) // salary is of type long
                    .ToList();

旧式sql命令

SELECT [c].[Salary] FROM [CustomerList] WHERE [c].[Age] > '30'

答案 2 :(得分:1)

这将帮助您更好地理解lambda表达式。 Anatomy of the Lambda Expression

这是给Linq

希望这会有所帮助。

谢谢。

答案 3 :(得分:1)

  

“哪里”如何获得对customerList的访问以及如何定义   “ c”的类型?

  • customerList的类型为List,Where()是List类型的扩展方法。因此Where()方法可用于customerList。 c => c.Age > 30Where()子句中的谓词定义。该谓词帮助列表可根据条件筛选出数据。这里的c表示列表中存在的单个元素。
  

“选择”如何确切地知道它仅返回   “薪水”?

  • Select用于从列表中投射单个元素,在您的情况下,customer中的每个customerList。由于Customer类包含名为long类型的Salary的属性,因此Select谓词将创建对象的新形式,该对象将仅包含Salary类的Customer属性的值。
  

变量“ salaries”的类型如何设置为List

  • Select()将仅使用Salary属性创建新表单,例如
new {
      public long Salary{get; set;}
    }

.ToList()会将Select返回的IEnumerable转换为List。最终,您会得到List<long>

  

“哪里”在应用了“   筛选器对Select起作用?

  • 是的,哪里将返回在其上应用了IEnumerable方法的过滤列表(精确度Select()

我建议您阅读Linq in C#Where clauseSelect methodList

答案 4 :(得分:1)

link from @Amit可以提供一个好主意。

最简单的答案是LINQ是基于称为Expressions的编译器功能构建的。当您编写类似Where(c => c.Age > 18)的内容时,编译器实际上并不会像常规方法一样完全编译c=> c.Age > 18

它建立一个语法树,描述该代码的作用。

Where函数使用它来构建一个SQL查询,该查询被发送到执行该SQL查询以获取结果的SQL服务器。

建议您查看IQueryableExpression<TDelegate>的工作原理以获取更多信息。

还有助于理解difference between IEnumerable and IQueryable

在C#其他部分(如Razor页面)中使用的表达式的另一个示例,其使用的函数类似LabelFor(...),该函数使用您 express 的属性来构建HTML标签,而不是执行代码。 / p>

HTH