Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This is easiest understood by looking at the code generated by the compiler, which is similar to:</p> <pre><code>public void AttachToAEvent() { _foo.AEvent += new EventHandler(this.Handler); } [CompilerGenerated] private void Handler(object sender, EventArgs e) { this.UseBar(this._bar); } </code></pre> <p>As can be plainly seen, the delegate created is an <em>instance</em>-delegate (targets an instance method on an object) and must therefore hold a reference to this object instance.</p> <blockquote> <p>Since delegate captures variable this._bar, does it implicitly hold to the instance of B?</p> </blockquote> <p>Actually, the anonymous method captures just <code>this</code> (not <code>this._bar</code>). As can be seen from the generated code, the constructed delegate will indeed hold a reference to the <code>B</code> instance. It has to; how else could the field be read on demand whenever the delegate is executed? Remember that <em>variables</em> are captured, not <em>values</em>.</p> <blockquote> <p>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.</p> </blockquote> <p>Yes, you have every reason to be. As long as the <code>A</code> instance is reachable, the <code>B</code> 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.</p> <blockquote> <p>Would it be different if _bar was a local variable of the AttachToAEvent method?</p> </blockquote> <p>Yes, it would, as the captured variable would then become the <code>bar</code> local rather than <code>this</code>. But assuming that <code>UseBar</code> 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 <code>B</code> object instance. </p> <p>This is accomplished by creating a closure object and making it (really an instance method of it) the target of the delegate.</p> <pre><code>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); } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload