使用起来没有什么问题this
在 lambda 中,但正如你提到的,如果你确实使用this
(或者,如果您通过调用任何非静态成员函数或使用非静态成员变量隐式使用它),那么垃圾收集器将保留该对象this
指的是至少只要代表还活着就活着。由于您将 lambda 传递给Lazy
,这意味着Repository
至少只要Lazy
对象还活着(即使你从不调用Lazy.Value
).
为了稍微揭开它的神秘面纱,查看反汇编程序会有所帮助。考虑这段代码:
class Foo {
static Action fLambda, gLambda;
int x;
void f() {
int y = 0;
fLambda = () => ++y;
}
void g() {
int y = 0;
gLambda = () => y += x;
}
}
标准编译器将其更改为以下内容(尝试忽略<>
额外的尖括号)。如您所见,使用函数体内变量的 lambda 被转换为类:
internal class Foo
{
private static Action fLambda;
private static Action gLambda;
private int x;
private void f()
{
Foo.<>c__DisplayClass1 <>c__DisplayClass = new Foo.<>c__DisplayClass1();
<>c__DisplayClass.y = 0;
Foo.fLambda = new Action(<>c__DisplayClass.<f>b__0);
}
private void g()
{
Foo.<>c__DisplayClass4 <>c__DisplayClass = new Foo.<>c__DisplayClass4();
<>c__DisplayClass.<>4__this = this;
<>c__DisplayClass.y = 0;
Foo.gLambda = new Action(<>c__DisplayClass.<g>b__3);
}
[CompilerGenerated]
private sealed class <>c__DisplayClass1
{
public int y;
public void <f>b__0()
{
this.y++;
}
}
[CompilerGenerated]
private sealed class <>c__DisplayClass4
{
public int y;
public Foo <>4__this;
public void <g>b__3()
{
this.y += this.<>4__this.x;
}
}
}
如果你使用this
,无论是隐式还是显式,它都成为编译器生成的类中的成员变量。所以该类为f()
, DisplayClass1
,不包含对Foo
,但是班级g()
, DisplayClass2
, does.
如果 lambda 不引用任何局部变量,编译器会以更简单的方式处理它们。所以考虑一些稍微不同的代码:
public class Foo {
static Action pLambda, qLambda;
int x;
void p() {
int y = 0;
pLambda = () => Console.WriteLine("Simple lambda!");
}
void q() {
int y = 0;
qLambda = () => Console.WriteLine(x);
}
}
这次 lambda 不引用任何局部变量,因此编译器将 lambda 函数转换为普通函数。中的 lambdap()
不使用this
所以它变成了一个静态函数(称为<p>b__0
);中的 lambdaq()
确实使用this
(隐式)因此它成为一个非静态函数(称为<q>b__2
):
public class Foo {
private static Action pLambda, qLambda;
private int x;
private void p()
{
Foo.pLambda = new Action(Foo.<p>b__0);
}
private void q()
{
Foo.qLambda = new Action(this.<q>b__2);
}
[CompilerGenerated] private static void <p>b__0()
{
Console.WriteLine("Simple lambda!");
}
[CompilerGenerated] private void <q>b__2()
{
Console.WriteLine(this.x);
}
// (I don't know why this is here)
[CompilerGenerated] private static Action CS$<>9__CachedAnonymousMethodDelegate1;
}
Note:我使用查看编译器输出ILSpy https://github.com/icsharpcode/ILSpy选项“反编译匿名方法/lambda”已打开off.