Note that there are some explanatory texts on larger screens.

plurals
  1. POIs this object-lifetime-extending-closure a C# compiler bug?
    text
    copied!<p>I was answering a <a href="https://stackoverflow.com/questions/8417470/private-field-captured-in-anonymous-delegate">question</a> about the possibility of closures (legitimately) extending object-lifetimes when I ran into some <em>extremely</em> curious code-gen on the part of the C# compiler (4.0 if that matters). </p> <p>The shortest repro I can find is the following:</p> <ol> <li>Create a lambda that captures a local while calling a <em>static</em> method of the containing type.</li> <li>Assign the generated delegate-reference to an <em>instance</em> field of the containing object.</li> </ol> <p>Result: The compiler creates a closure-object that references the object that created the lambda, when it has no reason to - the 'inner' target of the delegate is a <em>static</em> method, and the lambda-creating-object's instance members needn't be (and aren't) touched when the delegate is executed. Effectively, the compiler is acting like the programmer has captured <code>this</code> without reason.</p> <pre><code>class Foo { private Action _field; public void InstanceMethod() { var capturedVariable = Math.Pow(42, 1); _field = () =&gt; StaticMethod(capturedVariable); } private static void StaticMethod(double arg) { } } </code></pre> <p>The generated code from a release build (decompiled to 'simpler' C#) looks like this:</p> <pre><code>public void InstanceMethod() { &lt;&gt;c__DisplayClass1 CS$&lt;&gt;8__locals2 = new &lt;&gt;c__DisplayClass1(); CS$&lt;&gt;8__locals2.&lt;&gt;4__this = this; // What's this doing here? CS$&lt;&gt;8__locals2.capturedVariable = Math.Pow(42.0, 1.0); this._field = new Action(CS$&lt;&gt;8__locals2.&lt;InstanceMethod&gt;b__0); } [CompilerGenerated] private sealed class &lt;&gt;c__DisplayClass1 { // Fields public Foo &lt;&gt;4__this; // Never read, only written to. public double capturedVariable; // Methods public void &lt;InstanceMethod&gt;b__0() { Foo.StaticMethod(this.capturedVariable); } } </code></pre> <p>Observe that <code>&lt;&gt;4__this</code> field of the closure object is populated with an object reference but is never read from (there is no reason).</p> <p>So what's going on here? Does the language-specification allow for it? Is this a compiler bug / oddity or is there a good reason (that I'm clearly missing) for the closure to reference the object? This makes me anxious because this looks like a recipe for closure-happy programmers (like me) to unwittingly introduce strange memory-leaks (imagine if the delegate were used as an event-handler) into programs. </p>
 

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