【发布时间】:2010-12-05 21:17:06
【问题描述】:
我可以遵循任何简单的语法或规则在 C# 中构建“lambda 表达式”吗?我阅读了一些文章并理解了 lambda 表达式是什么,但如果我有通用的语法或规则会有所帮助。
【问题讨论】:
我可以遵循任何简单的语法或规则在 C# 中构建“lambda 表达式”吗?我阅读了一些文章并理解了 lambda 表达式是什么,但如果我有通用的语法或规则会有所帮助。
【问题讨论】:
有多种表达 lambda 的方式,具体取决于具体场景 - 一些示例:
// simplest form; no types, no brackets
Func<int, int> f1 = x => 2 * x;
// optional exlicit argument brackets
Func<int, int> f2 = (x) => 2 * x;
// optional type specification when used with brackets
Func<int, int> f3 = (int x) => 2 * x;
// multiple arguments require brackets (types optional)
Func<int, int, int> f4 = (x, y) => x * y;
// multiple argument with explicit types
Func<int, int, int> f5 = (int x, int y) => x * y;
lambda 的签名必须与所使用的委托的签名相匹配(无论是显式的,如上所示,还是由上下文隐含在诸如 .Select(cust => cust.Name) 之类的内容中)
您可以通过使用一个空的表达式列表来使用 lambdas 不带 参数:
// no arguments
Func<int> f0 = () => 12;
理想情况下,右边的表达式就是这样;一个表达式。编译器可以将其转换为或者 delegate 或 Expression 树:
// expression tree
Expression<Func<int, int, int>> f6 = (x, y) => x * y;
但是;你也可以使用语句块,但这只能用作delegate:
// braces for a statement body
Func<int, int, int> f7 = (x, y) => {
int z = x * y;
Console.WriteLine(z);
return z;
};
请注意,即使 .NET 4.0 Expression 树支持语句体,C# 4.0 编译器不会为您执行此操作,因此您仍然仅限于简单的 Expression 树,除非你用“艰难的方式”去做;请参阅my article on InfoQ 了解更多信息。
【讨论】:
从根本上说,lambda 表达式是函数指针的简写符号。更常见的是,lambda 表达式是将输入数据传播到计算结果的表达式中。在大多数情况下,您会以更常见的形式使用 lambda 表达式:
int[] numbers = new[] { 1, 3, 11, 21, 9, 23, 7, 4, 18, 7, 7, 3, 21 };
var twentyoneCount = numbers.Where(n => n == 21).Count();
var sumOfgreaterThanSeven = numbers.Sum(n => n > 7 ? n : 0);
在不太常见的形式中,lambda 表达式可以代替更繁琐的委托形式:
myButton.Click += new EventHandler(myButton_Click);
// ...
void myButton_Click(object sender, EventArgs e)
{
// TODO: Implement button click handler here
}
或者不那么常见,也不那么冗长:
myButton.Click += delegate(object sender, EventArgs e)
{
// TODO: Implement button click handler here
};
下面的 lambda 表达式实现了与上面两个相同的结果:
myButton.Click += (s,e) =>
{
// TODO: Implement button click handler here
};
后一种形式的强大之处在于其创建闭包的能力。闭包是您在函数内实现函数的地方,并在父函数范围内“关闭”参数和变量:
private void DoSomething(IList<string> input, SomeObject source)
{
source.OnSomeEvent += (s,e) => return input.Sum();
}
【讨论】:
.Compile()。典型的例子是 LINQ to SQL。它不会在您的表达式树上调用 compile 并且最终结果是 not 一个函数。这是一个生成的 SQL 语句。