代码之家  ›  专栏  ›  技术社区  ›  Homam

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

  •  2
  • Homam  · 技术社区  · 15 年前

    根据我所知道的,当我在C中定义一个方法时,这个方法中的局部变量将在执行完这个方法的块之后从内存中释放出来[当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();
        }
    
    1 回复  |  直到 15 年前
        1
  •  5
  •   Tomas Petricek    15 年前

    变量 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函数中实际使用的那些局部变量(因此,如果方法中有一些较大的数据,它们不会意外地保持比需要的时间长的活动状态)。