我正在研究C#7.0中的新实现,我觉得有趣的是他们已经实现了本地函数,但我无法想象一个局部函数比lambda表达式更受欢迎的场景,两者之间有什么区别.
我知道lambdas是anonymous函数,而局部函数却没有,但我无法弄清楚一个真实世界的场景,其中局部函数优于lambda表达式
任何例子都将非常感激.谢谢.
lambda表达式(以及程度,匿名函数)是否闭包?
我对闭包的理解是它们是被视为对象的函数,这似乎是匿名函数和Lambda表达式所做的准确表示.
称他们为封闭是否正确?我知道由于lisp方言,闭包产生(或变得流行),但它是否也是一般编程术语?
感谢您提供的任何澄清!
我觉得我对闭包有很好的理解,如何使用它们,以及它们什么时候有用.但我不明白的是他们实际上是如何在幕后的幕后工作的.一些示例代码:
public Action Counter()
{
int count = 0;
Action counter = () =>
{
count++;
};
return counter;
}
Run Code Online (Sandbox Code Playgroud)
通常,如果闭包没有捕获{count},它的生命周期将被限定为Counter()方法,并且在它完成之后它将消除Counter()的其余堆栈分配.什么时候关闭会发生什么?这个Counter()调用的整个堆栈分配是否存在?它会将{count}复制到堆中吗?它是否从未真正在堆栈上分配,但被编译器识别为关闭,因此总是存在于堆上?
对于这个特殊的问题,我主要关注它在C#中是如何工作的,但是不反对与支持闭包的其他语言进行比较.
当使用一个非常简单的表达式作为创建ILookup的键时,Enumerable.ToLookup<TSource,?TKey> Method (IEnumerable<TSource>,?Func<TSource,?TKey>)我可以使用lambda表达式:
var lk = myItems.ToLookup((x) => x.Name);
Run Code Online (Sandbox Code Playgroud)
或本地功能:
var lk = myItems.ToLookup(ByName);
string ByName(MyClass x)
{
return x.Name;
}
Run Code Online (Sandbox Code Playgroud)
我很好奇这个简单案例是否存在差异.
在他对Local函数vs Lambda C#7.0的回答中,SO用户svick给出了一个很好的论据 - 为什么-in general-局部函数比lambdas更好.
重要的一点是性能的差异:
创建lambda时,必须创建一个委托,在这种情况下这是一个不必要的分配.本地函数实际上只是函数,不需要代理.
但是因为ToLookup()无论如何我们都将它传递给了一个委托.性能还有差异吗?
我可以想象编译器必须为myItems.ToLookup的每次调用创建一个新的委托lambda,而本地方法只需要一个委托实例; 这是真的?
此外,本地函数在捕获局部变量时更有效:lambdas通常将变量捕获到类中,而本地函数可以使用struct(使用ref传递),这又避免了分配.
然而,因为表达不从外部范围使用变量,也不必是封闭的陈述由里德·科普塞和扩大通过埃里克利珀在回答在C#闭包是Lambda表达式?:
lambda可以使用闭包来实现,但它本身不一定是闭包.- Reed Copsey
[...]
一个可以被视为对象的函数只是一个委托.使lambda成为闭包的原因是它捕获了它的外部变量.- Eric Lippert
这多少有些矛盾埃里克利珀自己是他的回答到指定的本地函数来代表 埃里克利珀解释一个局部函数为命名的λ:
本地函数基本上只是一个带有关联名称的lambda.
但这是一个较小的技术细节和lambda/local函数的代表,它们捕获外部范围变量.
这个简单的表达式不是递归的,不是泛型的,也不是迭代器.看起来更好的是一个意见问题.
那么,简单的非捕获,非递归,非泛型和非迭代器lambda表达式和本地函数之间的性能(或其他)是否有任何差异?