Я отвечал на вопрос о возможности закрытия (законно) продления времени жизни объекта, когда столкнулся с каким-то чрезвычайно любопытным генератором кода со стороны компилятора C # ( 4.0, если это имеет значение).
Самое короткое повторение, которое я могу найти: ]
Результат: компилятор создает объект замыкания, который ссылается на объект, который создал лямбду, когда у него нет причин - «внутренняя» цель делегата - это статический метод , и к членам экземпляра объекта-лямбда-создания не нужно (и не нужно) прикасаться при выполнении делегата. По сути, компилятор действует так, как программист захватил this
без причины.
class Foo
{
private Action _field;
public void InstanceMethod()
{
var capturedVariable = Math.Pow(42, 1);
_field = () => StaticMethod(capturedVariable);
}
private static void StaticMethod(double arg) { }
}
Сгенерированный код из сборки выпуска (декомпилированной в «более простой» C #) выглядит следующим образом:
public void InstanceMethod()
{
<>c__DisplayClass1 CS[111]lt;>8__locals2 = new <>c__DisplayClass1();
CS[111]lt;>8__locals2.<>4__this = this; // What's this doing here?
CS[111]lt;>8__locals2.capturedVariable = Math.Pow(42.0, 1.0);
this._field = new Action(CS[111]lt;>8__locals2.b__0);
}
[CompilerGenerated]
private sealed class <>c__DisplayClass1
{
// Fields
public Foo <>4__this; // Never read, only written to.
public double capturedVariable;
// Methods
public void b__0()
{
Foo.StaticMethod(this.capturedVariable);
}
}
Обратите внимание, что поле <>4__this
объекта замыкания заполнено ссылкой на объект но никогда не читается (нет причин).