Lambda表达式语法

7

在使用LINQ时,是否必须使用lambda表达式,还是lambda表达式是可选的?

在lambda表达式中,符号=>总是被使用。它代表什么意思?

 customers.Where(c => c.City == "London"); 

这里为什么使用了c =>,使用c =>有哪些含义?请详细讨论,因为我不了解lambda。

7个回答

11

不,你不必使用lambda表达式。例如,你的Where示例可以这样写:

private static bool IsLondon(Customer customer)
{
    return customer.City == "London";
}

...

var londoners = customers.Where(IsLondon);

假设您正在使用LINQ to Objects。对于LINQ to SQL等,您需要构建表达式树。
至于为什么lambda表达式中始终使用"=>",那只是因为这就是操作符的写法 - 这就像询问为什么要使用加号进行加法一样。
"c => ..."的lambda表达式实际上为lambda表达式提供了一个名为“c”的参数。在这种情况下,泛型类型推断提供了“c”的类型。该代码块提供了基于“c”的某些计算的行动或返回值。
完整描述lambda表达式超出了此答案的范围。然而,在我的书的第9章详细介绍了它们。

7

lambda表达式

c => c.City == "London"

是类似于某物的速记方式

bool IsCustomerInLondon(Customer c)
{
  return (c.City == "London");
}

这只是一种非常简洁的编写返回值的简单函数的方式。它被称为“匿名函数”,因为它从未被分配名称或正式定义(参数类型和返回类型从上下文中推断出来)。
(实际上,这不仅仅是缩略语;lambda表达式与一些称为closures的其他构造有关,这些构造非常酷且功能强大。)

1
请注意,Lambda表达式也可以转换为表达式树。 - Jon Skeet

4

想象一下lambda函数就像是匿名函数。下面我会用代码来解释。

public bool IsLondon(Customer customer)
{
    return customer.City == "London";
}

现在我们要将函数名剥离并去掉括号:
public bool Customer customer    
    return customer.City == "London";

我们不需要返回类型,因为编译器可以从表达式中推断出类型:

 customer.City == "London";

以同样的方式,编译器知道输入类型,因此我们不需要指定它。因此,基本上,我们剩下的是:
customer
   return customer.City == "London";

在C#中,Lambda语法基本上是这样的:
(parameter list) => "expression"

您还可以编写“多行”表达式,但这时需要用花括号包围您的代码。此外,您需要使用"return"语句,就像通常一样。

1

Lambda和Linq是相互独立的。您可以使用其中一个而不使用另一个(尽管Linq的某些部分依赖于Lambda表达式,但我们希望保持简单:-))

lambda表达式是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式树类型。

这是来自MSDN的信息。(http://msdn.microsoft.com/en-us/library/bb397687.aspx)

简单来说(实际上更为复杂),您可以使用Lambda表达式来创建本地函数。在“=>”之前放置的内容(例如您的示例中的c)将成为该函数的参数。返回类型由C#编译器“发现”。

c => c.City == "London"几乎等同于:

delegate (TheObjectTypeOfC c) {
   return c.City == London
};

区别在于一些lambda表达式是委托,也是表达式,但请忽略这一点,您暂时不需要它。

如果/当编译器无法推断参数的类型时,您可以强制指定它们:(MyObject p) => p.SomeProperty != null。在这里,您告诉编译器p是一个参数。

虽然我在这里展示了所谓的“表达式lambda”,但您甚至可以做“语句lambda”:

p => {
   for (int i = 0; i < 10; i++) {
       if (p.SomeProperty == 0) {
          return true;
       }
   }

   return false;
}

(我不会告诉你表达式lambda和语句lambda之间的“幕后”区别。如果你想知道,读一下我之前指出的msdn页面)


它们并非完全分离,因为查询表达式(LINQ的一部分)的翻译依赖于Lambda表达式。然而,可以说您可以在不使用Lambda表达式的情况下使用LINQ库。 - Jon Skeet

1

Jon已经回答了,但我想补充一下。

在你给出的例子中,想象一下Linq循环遍历所有客户端,而c只是可枚举项中每个项目的引用:

var result = new List<Customer>();
foreach(var c in customers)
{
     if (c.City == "London")
        result.Add(c);   
}
return result;

它只是像其他任何变量一样,不一定要是单独命名的,但这只是某种约定俗成。


1

在 Linq to SQL 或 Entities 中,您不需要使用 lambda 表达式;这里是您代码的另一种替代方式:

您的代码:

customers.Where(c => c.City == "London");

另一种方式;

  var query = from cs in customers
              where cs.City == "London"
              select cs;

这是另一种方式。由你决定。


1

不,这完全不必要。

我们有两种方法来编写LINQ查询。

一种是查询方法,另一种是构建器方法。在构建器方法中,您只需要放置lambda表达式。例如,如果我们想要从某些学生对象中找到所有那些分数大于70的学生。但是我们可以使用以下语法在LINQ中完成此操作:

   var data = from p in stdList
   where p.marks > 70
   select p;

或者

var data = stdList.Where(p => p.marks > 70);

后一种方法是构建器方法,在Where函数中,我们传递lambda表达式。

Lambda表达式只是做事情的捷径,您始终可以使用LINQ查询,但如果您想避免整个查询语法仅应用简单条件,您可以使用LINQ构建器方法(要求lambda表达式)在lambda表达式中,您总是定义一些别名,然后执行操作。

就=>运算符而言,它的工作方式与赋值运算符相同。 例如:

(p) => p.Gender == “F”
It means  “All persons  p, such that person’s Gender is F”

在一些文献中,这被称为“谓词”。另一种文献术语是“投影”。
(p) => p.Gender ? “F” : “Female”
“Each person p becomes string “Female” if Gender is “F”” 

这是投影,它使用三元运算符。 虽然我用非常基本的例子来解释,但我希望这能帮到你。:)


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