Поиск

Почти совершенное решение

Итак, решения по управлению ресурсами не могут дать все и сразу. А если реализовать детерминированное завершение лишь для тех объектов, для которых оно, по вашему мнению, действительно нужно? Команда разработчиков .NET долго размышляла об этом. Не забывайте, что все это происходило в контексте необходимости точного дублирования семантики Visual Basic 6 в новой системе. Большая часть сделанных выводов применима и сейчас, но некоторые давно отброшенные идеи теперь выглядят привлекательно (например, методы управления ресурсами как альтернатива "прозрачной" семантике времени жизни в Visual Basic 6).

Первая попытка заключалась просто в том, чтобы пометить класс как требующий детерминированного завершения атрибутом или наследованием от "специального" класса. В результате этого производится подсчет ссылок на объект. Было проверено множество решений как с подклассами System.Object, так и с возможностью замены корня иерархии классов другим классом, чтобы объединить подход с подсчетом ссылок с альтернативными. Увы, при этом встретился ряд непреодолимых проблем, описанных ниже.

Объединение

Каждый раз, когда вы берете объект, требующий детерминированного завершения, и сохраняете в объекте, который этого не требует, вы теряете детерминированность (так как детерминированность не передается). Эта проблема наносит удар в самое сердце иерархии классов. Как быть, например, с массивами? Если вам нужен массив детерминированных объектов, то сами массивы должны быть детерминированными. А как насчет коллекций и хэш-таблиц? Список продолжается: забегая вперед, скажу, что подсчет ссылок используется всей библиотекой классов, что делает невозможным выполнение поставлётгей-задачя.

Другой альтернативой была бифуркация (т. е. разделение на две ветви) библиотеки классов .NET Framework и появление двух версий многих типов классов, например, детерминированных и недетерминированных массивов. Однако стало ясно, что наличие двух копий всей модели приведет к путанице, производительность в этом случае будет ужасной, так как будут загружаться две копии класса, и в конце концов это будет непрактично.

Изучались специфические решения для специфических классов, но ни одно из них даже не приблизилось к тому, чтобы быть решением общего назначения, масштабируемым в рамках всей модели. Обдумывали вариант, в котором фундаментальная проблема — случай, когда система теряет детерминированность, если недетерминированный объект содержит ссылку на детерминированный, — рассматривалась как ошибочная ситуация. Однако был сделан вывод, что это ограничение затруднит написание реальных программ.

Приведение

Во время приведения типов возникают сходные проблемы. Попробуйте ответить на такие вопросы: могу ли я привести детерминированный объект к System.Object! Если так, то будут ли при этом подсчитываться ссылки? Если да, то для любой сущности будет вестись подсчет ссылок, нет — объект теряет детерминированность, если же ответ — "ошибка", нарушается фундаментальная предпосылка, согласно которой System.Ob-ject — корень иерархии объектов.

Интерфейсы

Теперь вы видите, насколько сложна проблема. Если детерминированный объект реализует интерфейсы, то подсчитываются ли ссылки, типизированные как интерфейсные ссылки? Если да, то для всех реализующих интерфейсы объектов производится подсчет ссылок (заметьте, что System.Int32 реализует интерфейсы). Если нет, объект опять же теряет детерминированность. Если же ответ — "ошибка", детерминированный объект не может реализовывать интерфейсы. А если ответ звучит так: "это зависит от того, помечен ли интерфейс как детерминированный", то возникает еще одна проблема бифуркации. Интерфейсы не предназначены для определения времени жизни. Что, если кто-то реализует API, принимающий интерфейс ICollection и реализующий его ваш объект должен быть детерминированным, а сам интерфейс не был определен таким образом? При этом вам сильно не повезет. Согласно этому сценарию, будет нужно определить два интерфейса — детерминированный и недетерминированный, где каждый метод будет определен дважды (в каждом из интерфейсов). Вы не поверите, но рассматривалась даже идея создания средств автоматической генерации двух версий методов. Так, мысль погрязла в огромной сложности проблемы, и эта идея была отброшена.