在匿名委托拍摄的私人领域 [英] Private field captured in anonymous delegate

查看:114
本文介绍了在匿名委托拍摄的私人领域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

class A
{
   public event EventHandler AEvent;
}
class B
{
   private A _foo;
   private int _bar;

   public void AttachToAEvent()
   {
      _foo.AEvent += delegate()
      {
         ...
         UseBar(_bar);
         ...
      }
   }
} 

由于委托捕捉变量this._bar,它含蓄地抱到B的实例?将b的实例,可以通过一个实例,通过事件处理程序中引用并抓获变量?

Since delegate captures variable this._bar, does it implicitly hold to the instance of B? Will instance of B be referenced through event handler and captured variable by an instance of A?

难道是不同的,如果_bar是AttachToAEvent方法的局部变量?

Would it be different if _bar was a local variable of the AttachToAEvent method?

由于我的情况下A的一个实例住得很长,远远高于b的实例更小,我担心做这个导致内存泄露。

Since in my case an instance of A lives far longer and is far smaller than an instance of B, I'm worried to cause "memory leak" by doing this.

推荐答案

这是最简单的通过查看由编译器,它类似于生成的代码理解:

This is easiest understood by looking at the code generated by the compiler, which is similar to:

public void AttachToAEvent()
{
    _foo.AEvent += new EventHandler(this.Handler);
}

[CompilerGenerated]
private void Handler(object sender, EventArgs e)
{
    this.UseBar(this._bar);
}



由于可以清楚地看出,创建委托是的实例的-delegate(目标对象上的实例方法),因此必须坚持这个对象实例的引用。

As can be plainly seen, the delegate created is an instance-delegate (targets an instance method on an object) and must therefore hold a reference to this object instance.

由于委托捕获可变this._bar,它含蓄地抱到
b的实例呢?

Since delegate captures variable this._bar, does it implicitly hold to the instance of B?

其实,匿名方法捕获只这个(不是 this._bar )。如可以从生成的代码可以看出,构造委托将确实保持在 B 实例的引用。它有;怎么还能每当执行委托现场按需阅读?记住的变量的被捕获,不会的

Actually, the anonymous method captures just this (not this._bar). As can be seen from the generated code, the constructed delegate will indeed hold a reference to the B instance. It has to; how else could the field be read on demand whenever the delegate is executed? Remember that variables are captured, not values.

由于我的情况下A的一个实例住得很长,远远小于
高于b的一个实例,我很担心这样做
这会导致内存泄露。

Since in my case an instance of A lives far longer and is far smaller than an instance of B, I'm worried to cause "memory leak" by doing this.

是的,你有充分的理由。只要 A 实例可达,在 B 事件的用户仍然会到达。如果你不想去花哨弱的事件,你需要这样改写这个处理器是未注册的,当它不再是必需的。

Yes, you have every reason to be. As long as the A instance is reachable, the B event-subscriber will still be reachable. If you don't want to go fancy with weak-events, you need to rewrite this so the handler is unregistered when it is no longer required.

难道是不同的,如果_bar是
AttachToAEvent方法的局部变量?

Would it be different if _bar was a local variable of the AttachToAEvent method?

是的,它会,为捕获的变量将继而成为本地,而不是这个
,而假设 UseBar 是一个实例方法,你的问题(如果你想TOT认为这样的说法)刚刚变得更糟。编译器现在需要产生一个事件侦听器记住本地和包含 B 对象实例。

Yes, it would, as the captured variable would then become the bar local rather than this. But assuming that UseBar is an instance-method, your "problem" (if you want tot think of it that way) has just gotten worse. The compiler now needs to generate an event-listener that "remembers" both the local and the containing B object instance.

这是通过创建一个封闭的对象,使之(真的是它的实例方法)委托的目标来实现的。

This is accomplished by creating a closure object and making it (really an instance method of it) the target of the delegate.

public void AttachToAEvent(int _bar)
{
    Closure closure = new Closure();
    closure._bar = _bar;
    closure._bInstance = this;
    _foo.AEvent += new EventHandler(closure.Handler);
}

[CompilerGenerated]
private sealed class Closure
{
    public int _bar;
    public B _bInstance;

    public void Handler(object sender , EventArgs e)
    {
        _bInstance.UseBar(this._bar);
    }
}

这篇关于在匿名委托拍摄的私人领域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆