Когда целесообразно проверить, был ли удален этот объект, и выдать исключение ObjectDisposedException? - PullRequest
6 голосов
/ 27 мая 2011

В классе, который реализует IDisposable, когда разумно проверить, был ли удален объект, и выбросить ObjectDisposedException, если он был?Во всех открытых методах и свойствах (кроме Dispose)?Иногда?Никогда?

Ответы [ 5 ]

4 голосов
/ 27 мая 2011

Эту проверку следует реализовывать только в методах, которые не работают с удаленным объектом.

Например:
Если ваш класс закрывает соединения с базой данных или дескрипторы файлов в Dispose, все методыкоторым нужны эти соединения с базой данных или файловые дескрипторы, чтобы проверить, открыт ли экземпляр.

2 голосов
/ 27 мая 2011

Если объект поддерживает IsDisposed, сам этот метод никогда не должен выбрасывать; было бы правильно для многих других методов генерировать, если IsDisposed возвращает true, но исключение должно генерироваться этими методами, а не IsDisposed. Можно использовать служебный метод AssertNotDisposed, который будет генерировать, если объект будет удален, но такого поведения можно ожидать от метода с таким именем.

В противном случае, я хотел бы предположить, что во многих случаях полезно иметь объект, содержащий объект IDisposable, и иметь возможность утилизировать внутренний объект, сохраняя при этом полезное состояние. Например, объект, функция которого состоит в том, чтобы показывать и поддерживать немодальное диалоговое окно для получения информации от пользователя, может с пользой хранить копию содержимого полей даже после закрытия окна. Такой объект должен предоставлять метод «Закрыть», который удаляет внутренние одноразовые объекты, но сохраняет полезное состояние. Хотя он также может иметь метод Dispose, который будет вызывать метод Close, но при этом также будет установлен флаг «NoLongerValid», который вызовет сброс свойств поля, я не думаю, что это действительно добавит какое-либо значение.

Я допускаю, что многие случаи, когда объект может сохранять полезное состояние после его удаления, указывают на класс, который, возможно, следует разделить. Например, класс Font, возможно, следует разделить на одноразовый класс FontInfo (содержащий описание шрифта, но не дескриптор GDI) и класс IDisposable ReadyFont (наследующий FontInfo и инкапсулирующий объект шрифта GDI). Подпрограммы, в которых используется шрифт, могут проверять, был ли данный объект задан как FontInfo или ReadyFont; в первом случае они могли создать шрифт GDI, использовать его и выпустить; в последнем случае они могут использовать объект шрифта GDI ReadyFont и освободить его. Тогда создатель ReadyFont будет отвечать за обеспечение его очистки.

Как таковой, я не знаю, попытается ли система использовать объект GDI, связанный со свойством Font элемента управления, при рендеринге элемента управления, но я знаю, что он не будет кричать, если Font удален (даже если он удаляется перед назначением его свойству Font!). Элементы управления, безусловно, способны создавать новые шрифты GDI при необходимости; Я не знаю, всегда ли они создают новый шрифт GDI или делают это, только если старый был удален. Прежнее поведение может показаться более производительным, но если его не закодировать осторожно, это может вызвать проблемы, если один поток попытается удалить шрифт, пока другой поток его использует.

2 голосов
/ 27 мая 2011

Единственное, что действительно указано, это то, что public void Dispose() сам должен , а не что-либо выбрасывать.

И любой метод, которому нужны (не) управляемые ресурсы, должен выбрасывать.

Это оставляет, на мой взгляд, только несколько спорных случаев:

  • IsOpen, IsDisposed: я бы не бросил
  • другой IsSomeStatus: это зависит.*
  • Length, Count, Position: Я не думаю, что закрытый поток имеет длину, поэтому throw

Становится сложнее, когда класс объединяет (не связанные) функции, такие как Stream и Коллекция.Мы просто не должны этого делать.

1 голос
/ 27 мая 2011

Использование удаленного объекта - это ошибка программирования, которую вы хотите найти как можно быстрее.

Чем больше мест вы проверите, тем быстрее вы найдете ошибку.удаленный объект приведет к тому, что какое-то исключение другого типа (например, нулевой указатель) не запутает пользователя.

В других местах это зависит от приложения, если оно того стоит.

1 голос
/ 27 мая 2011

Как вы говорите, я бы реализовал эту проверку во всех открытых методах и свойствах, кроме Dispose и IsDisposed. Это стандартный шаблон , запрещающий разработчику использовать ваш тип из-за ошибочного представления, что он все еще действителен.

...