Я отвечал на вопрос о возможности закрытия (законно) продления времени жизни объектов, когда столкнулся с каким-то чрезвычайно любопытным генератором кода со стороны компилятора 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$<>8__locals2 = new <>c__DisplayClass1();
CS$<>8__locals2.<>4__this = this; // What's this doing here?
CS$<>8__locals2.capturedVariable = Math.Pow(42.0, 1.0);
this._field = new Action(CS$<>8__locals2.<InstanceMethod>b__0);
}
[CompilerGenerated]
private sealed class <>c__DisplayClass1
{
// Fields
public Foo <>4__this; // Never read, only written to.
public double capturedVariable;
// Methods
public void <InstanceMethod>b__0()
{
Foo.StaticMethod(this.capturedVariable);
}
}
Заметьте, что <>4__this
поле объекта замыкания заполнено ссылкой на объект, но никогда не читается из (нет причин).
Так что здесь происходит? Позволяет ли это спецификация языка? Это ошибка / странность компилятора или есть веская причина (которую я явно упускаю) для замыкания для ссылки на объект? Это вызывает у меня беспокойство, потому что это похоже на рецепт для программистов, удовлетворяющих замыканиям (таких как я), невольно вводить странные утечки памяти (представьте, если делегат использовался в качестве обработчика событий) в программах.
this
.