如何使用Lambda将LINQ推导式查询语法转换为方法语法

21

是否有一种工具、过程或解决方案,可以将以下LINQ查询语法转换为方法语法和Lambda表达式(点表示法)?我希望该解决方案能够将以下查询语法转换为方法语法,例如:

var filteredEmployees = 
    from employee in allEmployees
    where employee.DepartmentID < 4 && employee.EmployeeID < 10
    orderby employee.DepartmentID descending,
            employee.LastName descending
    select employee;

以下是

var filteredEmployees2 = allEmployees.Where(employee => ((employee.DepartmentID < 4) && (employee.EmployeeID < 10)))
        .OrderByDescending(employee => employee.DepartmentID)
        .ThenByDescending(employee => employee.LastName);

我希望能够通过这个来更好地学习方法语法。

4个回答

25

LINQPad是一个非常好的工具,可以满足你的需求。我从他们的网站上“偷”了下面这张截图,以更好地说明它的工作原理。如果你使用linq语法编写查询,你可以点击红色高亮显示的按钮来查看相应的lambda语法:enter image description here


1
我有LINQpad高级版,它是一个很棒的工具,可以查看Lambda表达式。我用它来进行大量的工作,比如原型应用程序和测试代码。感谢网页截图;它真的有助于传达重点。 - Mike Barlow - BarDev

13
如果我们强制查询语法返回IQueryable类型,那么我们就可以使用方法语法了。
在这里,我将查询更改为返回IQueryable类型:
IQueryable<Employee> filteredEmployees = 
    (from employee in allEmployees.AsQueryable()
    where employee.DepartmentID < 4 && employee.EmployeeID < 10
    orderby employee.DepartmentID descending,
            employee.LastName descending
    select employee);

Console.WriteLine(filteredEmployees.ToString());

在之前的代码中,我们将"AsQueryable()"添加到"allEmployees"列表类型中。现在返回类型将是IQueryable,所以"filteredEmployees"现在将是"IQueryable"类型。然后在"filteredEmployees"上,我们只需要调用"ToString()"方法。
并且以下内容将被写入控制台。
System.Collections.Generic.List`1[UserQuery+Employee]
     .Where(employee => ((employee.DepartmentID < 4) AndAlso (employee.EmployeeID < 10)))
     .OrderByDescending(employee => employee.DepartmentID)
     .ThenByDescending(employee => employee.LastName)

虽然不完美,但我们可以轻松地将其编辑成以下形式

IEnumerable<Employee> filteredEmployees2 = allEmployees
        .Where(employee => ((employee.DepartmentID < 4) && (employee.EmployeeID < 10)))
        .OrderByDescending(employee => employee.DepartmentID)
        .ThenByDescending(employee => employee.LastName);

Console.WriteLine(filteredEmployees);

在之前的代码中,我删除了"System.Collections.Generic.List`1[UserQuery+Employee]"并用"allEmployees"替换了它。 我还用"&&"替换了"AndAlso"。
这将返回与查询语法中相同的结果。

这将创建一个表达式树 filteredEmployees.Expression - Mike Barlow - BarDev

3

通过声明一个生成某个对象的lambda表达式,您可以获得更直接的表达。实际的表达式将是使用查询语法想要查看的查询。然后通过检查编译器生成的表达式树,您可以看到进行了哪些方法调用,而无需改变原始查询。

Expression<Func<object>> fn = () =>
    from employee in allEmployees
    where employee.DepartmentID < 4 && employee.EmployeeID < 10
    orderby employee.DepartmentID descending,
            employee.LastName descending
    select employee;
// inspect fn.Body

使用IQueryable<>并不会生成与您之前所做的相同的查询,但会稍微修改。您需要忽略AsQueryable()调用。此外,查询提供程序可以重写表达式,因此使用ToString()得到的结果可能不具有1:1的对应关系。编译器生成的表达式将完全符合您的期望。


0

我发现最简单的方法是使用Visual Studio内置的Action功能:

screenshot

它可以将这个转换成:

from numberA in numbersA
                from numberB in numbersB
                where numberA < numberB
                select (numberA, numberB)).ToList();

转换为:

numbersA.SelectMany(numberA => numbersB, (numberA, numberB) => new { numberA, numberB })
                .Where(t => t.numberA < t.numberB)
                .Select(t => (t.numberA, t.numberB)).ToList();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接