【问题标题】:Lambda expression syntactic sugar?Lambda 表达式语法糖?
【发布时间】:2011-07-12 14:56:45
【问题描述】:

我刚刚遇到以下代码 (.NET 3.5),它看起来不应该对我编译,但它可以编译,并且工作正常:

bool b = selectedTables.Any(table1.IsChildOf));

Table.IsChildOf 实际上是一个具有以下签名的方法:

public bool IsChildOf(Table otherTable)

我认为这相当于:

bool b = selectedTables.Any(a => table1.IsChildOf(a));

如果是这样,正确的说法是什么?

【问题讨论】:

标签: c# lambda syntactic-sugar


【解决方案1】:

这是一个方法组转换,它从 C# 2 开始就可用。作为一个更简单的例子,考虑:

public void Foo()
{
}

...

ThreadStart x = Foo;
ThreadStart y = new ThreadStart(Foo); // Equivalent code

请注意,这与 lambda 表达式版本完全相同,后者将捕获 变量 table1,并生成一个新类,其中包含一个方法只需致电IsChildOf。对于Any,这并不重要,但区别对于Where 很重要:

var usingMethodGroup = selectedTables.Where(table1.IsChildOf);
var usingLambda = selectedTables.Where(x => table1.IsChildOf(x));
table1 = null;

// Fine: the *value* of `table1` was used to create the delegate
Console.WriteLine(usingMethodGroup.Count());

// Bang! The lambda expression will try to call IsChildOf on a null reference
Console.WriteLine(usingLambda.Count());

【讨论】:

  • 你的意思是第一个是闭包,而 lambda 不是?
  • @Can: 反过来 - lambda 是一个闭包,捕获 table1。
  • 是的,我现在明白了。这些事情很容易让人困惑:)这也将是一个闭包,对吧? selectedTables.Where(delegate(Table table) { return table1.IsChildOf(table); });
  • @Can:是的 - 这是 C# 2 中的匿名方法。C# 3 中的 Lambda 表达式几乎完全取代了匿名方法。
【解决方案2】:

表达式table1.IsChildOf 称为method group

你是对的,它是等价的,这确实是句法糖。

【讨论】:

  • 这并不是真正的等价 - 对于 Any 结果将是相同的(除非有另一个线程涉及更改 table1 的值)但通常可能存在显着差异。例如,请参阅我的答案。
  • @Jon:你当然是对的,你对幕后发生的事情的解释非常有价值。但在我的辩护中,在枚举查询之前更改 table1 的值并不是你每天都能看到的。
  • @Jon:没错,但鉴于许多 LINQ 运算符的惰性,我认为了解捕获的工作原理(与方法组转换相比)很重要。
  • @Jon:同意。现在,如果我们能让每个人都了解关闭... ;)
  • @Jon 和@Jon,Resharper 曾经有一个错误,它落入了 Skeet 先生指出的确切陷阱。 Event1 += (o, e) => Event2(o, e); 将“链接”事件,导致Event2Event1 触发时触发。但是 Resharper 很乐意建议替代 Event1 += Event2,这是完全不同的:它立即将 Event2 中的任何处理程序当前复制到 Event1 的列表中。通常结果是事件没有按预期传递(因为在复制发生时Event2 可能仍然是一个空列表)。
【解决方案3】:

它被称为方法组。 Resharper 鼓励使用这种代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-05
    • 2011-07-04
    • 2021-07-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    相关资源
    最近更新 更多