Ste*_*ris 43 c# lambda delegates
Lambdas很不错,因为它们提供简洁和局部性以及额外形式的封装.而不必编写只使用一次可以使用lambda的函数.
在想知道它们是如何工作的时候,我直觉地认为它们可能只创建过一次.这激发了我创建一个解决方案,该解决方案允许通过使用lambda作为其创建范围的标识符,将类成员的范围限制在私有范围之外.
这种实现虽然可能有些过分(仍在研究它),但可以证明我的假设是正确的.
一个较小的例子:
class SomeClass
{
public void Bleh()
{
Action action = () => {};
}
public void CallBleh()
{
Bleh(); // `action` == {Method = {Void <SomeClass>b__0()}}
Bleh(); // `action` still == {Method = {Void <SomeClass>b__0()}}
}
}
Run Code Online (Sandbox Code Playgroud)
lambda会返回一个新实例,还是保证总是相同?
Jon*_*eet 30
无论如何都无法保证.
从我记得的当前MS实现:
编辑:C#4规范的相关文本见6.5.1节:
将具有相同(可能为空)的捕获的外部变量实例集的语义相同的匿名函数转换为相同的委托类型是允许(但不是必需的)返回相同的委托实例.这里使用术语相同的术语来表示在所有情况下,在给定相同参数的情况下,匿名函数的执行将产生相同的效果.
Eri*_*ert 30
根据你在这里提出的问题以及你对Jon的答案的评论,我认为你混淆了很多事情.为了确保清楚:
所以如果你有类似的东西:
for(i = 0; i < 10; ++i)
M( ()=>{} )
Run Code Online (Sandbox Code Playgroud)
然后每次调用M时,都会获得相同的委托实例,因为编译器是智能的并且生成
static void MyAction() {}
static Action DelegateCache = null;
...
for(i = 0; i < 10; ++i)
{
if (C.DelegateCache == null) C.DelegateCache = new Action ( C.MyAction )
M(C.DelegateCache);
}
Run Code Online (Sandbox Code Playgroud)
如果你有
for(i = 0; i < 10; ++i)
M( ()=>{this.Bar();} )
Run Code Online (Sandbox Code Playgroud)
然后编译器生成
void MyAction() { this.Bar(); }
...
for(i = 0; i < 10; ++i)
{
M(new Action(this.MyAction));
}
Run Code Online (Sandbox Code Playgroud)
每次都会使用相同的方法获得新的委托.
允许编译器(但实际上此时不生成)生成
void MyAction() { this.Bar(); }
Action DelegateCache = null;
...
for(i = 0; i < 10; ++i)
{
if (this.DelegateCache == null) this.DelegateCache = new Action ( this.MyAction )
M(this.DelegateCache);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,如果可能,您将始终获得相同的委托实例,并且每个委托都将由相同的方法支持.
如果你有
Action a1 = ()=>{};
Action a2 = ()=>{};
Run Code Online (Sandbox Code Playgroud)
然后在实践中,编译器将其生成为
static void MyAction1() {}
static void MyAction2() {}
static Action ActionCache1 = null;
static Action ActionCache2 = null;
...
if (ActionCache1 == null) ActionCache1 = new Action(MyAction1);
Action a1 = ActionCache1;
if (ActionCache2 == null) ActionCache2 = new Action(MyAction2);
Action a2 = ActionCache2;
Run Code Online (Sandbox Code Playgroud)
但是,允许编译器检测到两个lambda是相同的并生成
static void MyAction1() {}
static Action ActionCache1 = null;
...
if (ActionCache1 == null) ActionCache1 = new Action(MyAction1);
Action a1 = ActionCache1;
Action a2 = ActionCache1;
Run Code Online (Sandbox Code Playgroud)
那现在清楚了吗?