当使用非常简单的表达式作为键来创建一个ILookup时,可以使用lambda表达式,具体方法请参考Enumerable.ToLookup<TSource, TKey> Method (IEnumerable<TSource>, Func<TSource, TKey>)
。
var lk = myItems.ToLookup((x) => x.Name);
或者是一个本地函数:
var lk = myItems.ToLookup(ByName);
string ByName(MyClass x)
{
return x.Name;
}
我很好奇在这个简单的情况下是否有区别。
在Local function vs Lambda C# 7.0中,SO用户svick 在他的回答中提出了一个好的论点,即通常情况下本地函数比lambda更可取。
重要的一点是性能上的差异:
创建lambda时,必须创建委托,在这种情况下,这是不必要的分配。本地函数只是函数,不需要委托。
但是因为我们将它传递给
ToLookup()
,所以仍然会创建委托。性能上还有区别吗?
我可以想象编译器必须为每次调用myItems.ToLookup创建一个新的委托lambda,而对于本地方法只需要一个委托实例;这是真的吗?在svick的答案中,性能的第二个不同点是变量的捕获和闭包的创建:
此外,本地函数在捕获本地变量方面更加高效:lambda通常将变量捕获到类中,而本地函数可以使用一个结构体(通过ref传递),这样可以避免分配。
然而,由于表达式没有使用外部作用域的变量,因此不必像Reed Copsey所述,并且Eric Lippert在回答C#中的Lambda表达式是否为闭包?时进行了扩展。
一个lambda可能是使用闭包实现的,但本身并不一定是闭包。 — Reed Copsey
[...]
一个可以被视为对象的函数只是一个委托。使lambda成为闭包的是它捕获了外部变量。 — Eric Lippert
这在某种程度上与Eric Lippert自己在答案中将局部函数分配给委托中所说的相矛盾。Eric Lippert将局部函数解释为一种命名lambda:
局部函数基本上只是一个带有关联名称的lambda。
但这在技术细节方面比较次要,仅适用于捕获外部作用域变量的lambda/local functions的委托。
这个简单的表达式不是递归的,也不是通用的,也不是迭代器。哪一个更好看是一个主观看法。
那么,在简单的不捕获、非递归、非通用和非迭代器的lambda表达式和本地函数之间有什么性能(或其他方面)上的区别吗?