Отказ от ответственности :
Я не могу гарантировать, что это 100% правда - ваш вопрос достаточно глубокий, и я могу ошибиться.
Тем не менее, я надеюсь, что это даст вам некоторые мысли или указания.
Давайте рассмотрим этот вопрос согласно CLR
организации памяти:
Локальные переменные метода и параметры метода хранятся в кадре стека методов в памяти (кроме случаев, когда они объявлены с ключевым словом ref
).
Стек хранит типы значений и ссылки на переменные ссылочного типа, которые указывают на объекты в куче.
Фрейм стека метода существует во время выполнения метода, а локальные переменные метода исчезнут вместе с фреймом стека после завершения метода.
За исключением случаев, когда локальные переменные были захвачены так или иначе, это также относится к работе компилятора , вы можете прочитать об этом на сайте Джона Скита:
http://jonskeet.uk/csharp/csharp2/delegates.html#captured.variables
Версия 1 : OnSomeEvent
метод является членом MyClass
и будет перехвачен экземпляром Someclass source
, пока делегаты, ссылающиеся на этот метод, не будут удалены из события. Таким образом, экземпляр MyClass
, созданный в конструкторе, помещенный в кучу и содержащий этот метод, не будет собираться GC
, пока ссылка на его метод не будет удалена из события.
Компилятор компилирует лямбду особым образом, прочитайте Пример реализации абзац полностью:
https://github.com/dotnet/csharplang/blob/master/spec/conversions.md#anonymous-function-conversions
Версия 4 :
2 ссылки, которые я дал, лямбда будет скомпилирована в метод MyClass
, который будет перехвачен экземпляром SomeClass
, как в Версия 1
Версия 2 :
Я не знаю нюансов о том, как будут компилироваться локальные методы, но он должен быть таким же, как в Версия 4 (и, следовательно, Версия 1 ).
Версия 3 :
Все локальные переменные будут захвачены интересным способом.
У вас также есть «объект x», поэтому будет создан сгенерированный компилятором класс, который
будет содержать открытое поле public object x;
и метод, который будет переведен из вашей лямбды (см. Пример реализации параграф).
Итак, я думаю, что в версии 1,2,4 внутренне будут одинаковыми:
MyClass будет содержать метод, который будет использоваться в качестве обработчика событий.
В версии 3 будет создан сгенерированный компилятором класс, в котором будут храниться ваша локальная переменная и метод, переведенные из lamdba.
Любой экземпляр любого класса не будет собираться GC до тех пор, пока у SomeClass
не появится метод в списке вызовов.