Разрешение правила анализа кода CA2000 в этом сценарии?

Я выполняю полный анализ кода в своем проекте, и он говорит, что у него 500 проблем. Сейчас я сократил его до 300, но я борюсь с проблемой, для которой не могу найти решения.

Правило CA2000 гласит:

Если одноразовый объект не удаляется явно до того, как все ссылки на него будут вне области действия, объект будет удален в неопределенное время, когда сборщик мусора запустит финализатор объекта. Поскольку может произойти исключительное событие, препятствующее запуску финализатора объекта, вместо этого объект должен быть удален явно.

Более подробную информацию о правиле можно найти на странице, указанной выше.

Код, в котором правило не работает, таков:

internal Window(Game game, Control parent, string title, bool visible)
    : base(game, parent, visible, new ScreenspaceRectangle(game, Color.Black, Vector.Zero, Vector.Zero))
{
}

А описание такое:

CA2000: Microsoft.Reliability: в методе «Window.Window(Game, Control, string, bool)» вызовите System.IDisposable.Dispose для объекта «new ScreenspaceRectangle(game, Color.Black, Vector.Zero, Vector.Zero)» прежде чем все ссылки на него выходят за рамки.

Я понимаю, что эту проблему можно решить обычным образом, используя оператор «using» вокруг создаваемого объекта, чтобы убедиться, что он всегда правильно утилизирован. Но как решить в этом случае?


person Mathias Lykkegaard Lorenzen    schedule 31.07.2011    source источник
comment
Почему ScreenspaceRectangle вообще нужно удалять?   -  person    schedule 31.07.2011


Ответы (2)


Предполагая, что класс Window является вашим пользовательским классом, вы должны убедиться, что конструктор базового класса хранит ссылку на ScreenspaceRectangle, если она требуется вне конструктора, и реализует IDisposable и удаляет экземпляр ScreenspaceRectangle в методе Dispose.

В противном случае убедитесь, что объект удаляется в конструкторе базового класса.

person Purvi    schedule 31.07.2011

Одно досадное ограничение c#/vb.net заключается в том, что они не позволяют оборачивать связанные конструкторы или инициализаторы полей в блок try-catch или try-finally. Если создание объекта Foo требует создания некоторых других объектов IDisposable, за удаление которых будет отвечать Foo, может быть трудно гарантировать, что эти объекты будут удалены, если исключение будет вызвано конструктором Foo, его подтипом или его супертип. Самый простой известный мне способ справиться с этим - использовать защищенный конструктор, обернутый в фабричные методы, которые создадут экземпляр "диспетчера одноразовых изделий" и пропустят его через цепочку конструкторов. Все, что может создать IDisposable, должно добавить его в менеджер расходных материалов; если конструктор выдает исключение, менеджер расходных материалов удалит все зарегистрированные расходные материалы.

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

person supercat    schedule 01.08.2011