Да, в вашем коде есть ссылочный цикл. Он создается с помощью анонимного метода захвата переменной метода.
Анонимные методы поддерживаются ссылочным подсчетом, сгенерированным компилятором. Любые переменные, захваченные анонимным методом, сохраняются как поля в одном классе. Компилятор создает экземпляр этого класса и сохраняет его в памяти, пока анонимный метод находится в области видимости.
Теперь для создания цикла было бы недостаточно данных. Но тот же экземпляр (тот же класс) будет использоваться для резервного копирования всех анонимных методов в рамках некоторой процедуры.
Переведено на ваш код:
TreeдержитTForm1TreeдержитCatalogCatalogдержитTree
Никаких циклов там - Mainне ссылается Catalog, ни CatalogссылкиMain
Но, когда вы смотрите на свою Treeпроцедуру, все меняется.
Анонимные методы Eventбудут поддерживаться экземпляром скрытого объекта, поэтому давайте посмотрим, что будет там:
- Первый анонимный метод
- Второй анонимный метод
Events- захвачен вторым анонимным методом
Все еще нет видимых циклов, но затем вы добавляете первый анонимный метод Eventв Treeсписок, который удерживается . Чтобы сохранить этот метод в живых, весь поддерживающий объект также будет сохранен.Anonymous method object -> Event -> Tree -> Events -> Event -> Anonymous method object
Tree
Чтобы разорвать этот цикл, вам нужно очистить некоторые ссылки. Например установить , Treeчтобы nilгде - нибудь в Main.