.NET do lambdas是否可以防止垃圾收集中使用的外部引用?

f0r*_*0rt 6 .net c# lambda garbage-collection

这是一个例子:

var task = Task.Run();
var func = () => task.Result;
Run Code Online (Sandbox Code Playgroud)

所以,如果我松开任务引用并保持func引用,GC将收集任务并使func抛出null引用异常?

Jon*_*eet 10

否.匿名函数捕获变量,至少在委托或表达式树被垃圾收集时延长其生命周期.

从C#5规范,第7.15.5.1节:

当外部变量由匿名函数引用时,外部变量被称为已由匿名函数捕获.通常,局部变量的生命周期仅限于执行与之关联的块或语句(第5.1.7节).但是,捕获的外部变量的生命周期至少会延长,直到从匿名函数创建的委托或表达式树符合垃圾回收的条件.

请注意,它是捕获的变量,而不是当时变量的值.因此,如果您将代码更改为:

var task = Task.Run(...);
var func = () => task.Result;
task = null;
Run Code Online (Sandbox Code Playgroud)

...然后原始文件Task 可以被垃圾收集,如果你调用它,代理将抛出异常,因为它将使用变量的当前task.