首页 > 解决方案 > “在哪里”和“选择”如何在 LINQ 中工作?

问题描述

我有以下代码片段。我对后面提到的代码片段几乎没有疑问。

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

标签: c#linq

解决方案


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。因为它是 a IEnumerable<Customer>Tis Customer,所以它期望 aFunc<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调用返回 a IEnumerable<long>,并且ToList的签名告诉编译器,给定 aIEnumerable<T>它将返回List<T>,所以在这种情况下,它返回 a List<long>


推荐阅读