E>В ходе обсуждения различных моментов при разработке программы, пришли к выводу, что нужны "слабые" ссылки.
E>Как быть? E>Как лучше сделать?
E>Среда очень похожа на старый Visual Basic 6 из старой Visual Studio.
Может быть решением проблемы — метод аналогичный Dispose()?
bnk>То есть, сборка мусора в твоей среде отстутствует, но есть подсчет ссылок. У VB6/VBA так например
Да, точно. Очень похоже.
bnk>В контексте MVP лучше говорить не о "слабых ссылках", а о подписке на события, IMHO. bnk>Суть от этого не изменяется.
Ну, при подписке источник событий тоже держит ссылку подписчика.
Подписчик не сможет освободить память пока источник событий не освободил на него ссылки.
Здравствуйте, es3000, Вы писали: Q>>1) Какие встроенные/библиотечные контейнеры поддерживаются?
E>Есть аналог коллекций — просто список ссылок. E>Есть структура (хранит ключ + значение). E>Есть аналог таблицы (список строк с колонками), но хранится в памяти.
Q>>2) Есть ли поддержка шаблонов/дженериков?
E>Нет.
Q>>3) Можно ли в классы добавлять статические/глобальные поля?
E>Нет.
Q>>4) Поддерживаются ли вложенные классы?
E>Нет.
Не густо.
Тогда так.
Пусть есть два класса Foo и Bar, для которых мы хотим поддерживать слабые ссылки.
Делаем два вспомогательных класса FooWeakRef и BarWeakRef.
Классы xxxWeakRef имеют конструктор, принимающий id и конструктор без параметров для создания пустой ссылки.
id хранится в единственном поле.
Деструктор ничего не делает!
Для получения доступа к объекту делаем метод Get без параметров, который возвращает сильную ссылку (на Foo или Bar, соответственно).
В своей реализации метод будет обращаться к глобальному контейнеру, откуда вытаскивать ссылку по id (про это ниже).
Если id — пустой (был вызван конструктор без параметров) или по id не найдена ссылка в контейнере (объект удален — на то ссылка у нас и слабая), то метод Get() возвращает пустую ссылку.
Теперь делаем два глобальных контейнера из разряда ключ+значение: FooRefMap и BarRefMap.
Ключом будет id, а значением соответствующая сильная ссылка.
Если в качестве id использовать целочисленные значения (а не GUID, к примеру), то потребуются еще глобальные переменные-счетчики FooRefIdCounter и BarRefIdCounter.
При добавлении элемента в FooRefMap будем инкрементировать значение FooRefIdCounter.
Далее делаем функции помощники для создания и удаления объектов класса Foo (и Bar).
Для создания делаем пачку функции id FooCreate(...), по одной на каждый конструктор Foo.
Для удаления — FooDestroy(id).
Функции FooCreate создают по new новый объект Foo, инкрементируют FooRefIdCounter и заносят пару id+ссылка в FooRefMap, а затем возвращают наружу новый id.
Функция FooDestroy удаляет из FooRefMap элемент по ключу id, при это сам объект разрушается, если на него нет ссылок где-то во временных локальных переменных.
Далее можно автоматизировать вызов функций FooCreate и FooDestroy в классе FooStrongRef — ссылки с семантикой владения.
В нем также запоминаем только id, а в деструкторе вызываем FooDestroy(id).
Метод Get() работает также, как в классе FooWeakRef.
Можно сделать метод FooWeakRef GetWeak(), который будет порождать слабую ссылку FooWeakRef, связанную с нашим id.
В результате в прикладном коде пользуемся только классами FooStrongRef/FooWeakRef (и BarStrongRef/BarWeakRef).
xxxStrongRef — для управления временем жизни, а xxxWeakRef — для слабых связей.
Здравствуйте, es3000, Вы писали:
E>Как быть? E>Как лучше сделать?
Изготовить полноценные слабые ссылки в абстрактной хорошо типизированной среде со сборщиком мусора невозможно.
Нужно знать, что это за среда — какие хаки в ней доступны.
К примеру, можно ли перегружать финализаторы; есть ли возможность "подсмотреть" значение ссылки на объект так, чтобы о ней не ведал GC, и т.п.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.