3

以下陈述完全可以。

var sb = new string[] { "line1", "line2" };
sb.ForEach(Console.WriteLine); 
// same as sb.ForEach(item => Console.WriteLine(item));

这种不使用 lambda 表达式中的参数的做法叫什么名字?

谢谢,

4

3 回答 3

10

“方法组转换”是您正在寻找的术语。它自动将一组方法(重载)转换为委托。

在这种情况下,Console.WriteLine是一组大约 19 个不同的方法,它们都以相同的名称重载。然后编译器确定这些重载之一是否与预期的委托兼容(Action<String>是唯一的委托)。由于有一个匹配,它会为您转换Console.WriteLinenew Action<String>(Console.WriteLine)

于 2012-07-05T20:06:38.790 回答
9

将形式的 lambda 转换Method(x => f(x))Method(f)称为eta reduction。我不知道 C# 编译器是否在内部执行 eta 缩减,但它确实支持将方法组(在您的情况下为 Console.WriteLine)转换为委托类型(可能Action<string>在这里)。

C# 编译器会将重载包装Console.WriteLine(string)Action<string>委托中并将其传递给您的ForEach方法。

C# 规范定义了将方法组转换为兼容委托类型的规则:

6.6 方法组转换

从方法组(第 7.1 节)到兼容委托类型存在隐式转换(第 6.1 节)。给定一个委托类型 D 和一个被归类为方法组的表达式 E,如果 E 包含至少一个适用于其正常形式(第 7.5.3.1 节)构造的参数列表的方法,则存在从 E 到 D 的隐式转换通过使用 D 的参数类型和修饰符

于 2012-07-05T20:07:53.410 回答
-1

虽然前面的两个答案都很好 - 并且正确 - 如果您有如下代码,还有一个额外的答案:

int i = 7;
return () => Foo(i);

这就是所谓的闭包,因为虽然 lambda 没有参数,但它将整数包含在父作用域中。当使用返回的匿名方法时,它仍然可以使用变量 i,就好像它从未超出范围一样......而且因为它是封闭的,所以它没有!

根据您的原始问题,您展示了 eta 减少或方法组转换。你的问题措辞听起来有点像结束语。

于 2012-07-09T14:03:34.183 回答