Является ли этот объект-расширение-срок-закрытие ошибкой компилятора C #?

Я отвечал на вопрос о возможности закрытия (законно) продления времени жизни объекта, когда столкнулся с каким-то чрезвычайно любопытным генератором кода со стороны компилятора C # ( 4.0, если это имеет значение).

Самое короткое повторение, которое я могу найти: ]

  • Назначьте сгенерированную ссылку на делегат полю instance содержащего объекта.
    1. Результат: компилятор создает объект замыкания, который ссылается на объект, который создал лямбду, когда у него нет причин - «внутренняя» цель делегата - это статический метод , и к членам экземпляра объекта-лямбда-создания не нужно (и не нужно) прикасаться при выполнении делегата. По сути, компилятор действует так, как программист захватил 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 объекта замыкания заполнено ссылкой на объект но никогда не читается (нет причин).

      1117 Так что же здесь происходит? Позволяет ли это спецификация языка? Это ошибка / странность компилятора или есть веская причина (которую я явно упускаю) для замыкания для ссылки на объект? Это вызывает у меня беспокойство, потому что это похоже на рецепт для программистов, удовлетворяющих замыканиям (таких как я), невольно вводить странные утечки памяти (представьте, если делегат использовался в качестве обработчика событий) в программах.

    136
    задан Community 23 May 2017 в 12:01
    поделиться