据我所知,当我在C#中定义一个方法时,该方法中的局部变量将在执行完该方法的 block 后从内存中释放[当GC想要时],
但是如果我在方法中有内联回调,这些局部变量也会从内存中释放吗?
在下面的示例中,[x] 变量在执行完方法后将保持其值,并且消息将毫无问题地显示 [x] 的值,尽管它是在回调中!!
private void MyMethod()
{
int x = 1;
System.Timers.Timer t = new System.Timers.Timer(1000);
t.Elapsed += (sender, e) => MessageBox.Show((x++).ToString()); ;
t.Start();
}
最佳答案
变量x
在与lambda函数关联的闭包中被捕获。这意味着 x
的值实际上并不存储在与 MyMethod
执行相关的堆栈上,而是存储在堆上(在 lambda 函数引用的对象中)。
以下示例(粗略地)显示了 C# 编译器如何转换代码:
class $$MyMethod$$Closure {
public int x;
void Function(object sender, EventArgs e) {
MessageBox.Show((x++).ToString());
}
}
private void MyMethod() {
var $$closure = new $$MyMethod$$Closure();
$$closure.x = 1;
System.Timers.Timer t = new System.Timers.Timer(1000);
t.Elapsed += $$closure.LambdaFunction;
t.Start();
}
如您所见,x
变量现在存储在堆分配的对象中(称为闭包)。只要计时器可以调用该方法(并且可以访问 x
),该对象就会处于事件状态,但是一旦删除计时器,闭包也将被垃圾收集。
值得注意的是,编译器仅捕获那些在 lambda 函数中实际使用的局部变量(因此,如果方法中有一些大数据,它们不会意外地保持事件状态)比需要的时间长)。
关于c# - 内联代码执行完成后是否将[写入其中的]方法保留在内存中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3073714/