c# - 内联代码执行完成后是否将[写入其中的]方法保留在内存中?

标签 c# .net callback

据我所知,当我在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/

相关文章:

c# - 如何使用 C#.NET 合并在 MS Word 中创建的表格的单元格?

asynchronous - 如何在回调中使用 Rust future?

jquery - 无法将内容附加到 Sidr

javascript - 无法直接为JSX子元素的点击事件添加回调函数

.net - 在 .Net 项目中配置和使用 Broker API

c# - 如何优雅地保护方法免受未初始化接口(interface)参数的影响

c# - 您如何在 .NET 的算法代码中断言?

c# - 在线 CRM REST 服务 - 遇到问题

c# - 为什么使用不存在的字体也没有异常?

c# - SignalR 向特定客户端发送消息