Если есть разумная вероятность того, что абстрактный объект (интерфейс или абстрактный класс) может быть одноразовым , он должен это реализовать. Поток
, например, сам не требует IDisposable
, равно как и IEnumerator
...
Абстрактная база class может быть проще, так как вы можете иметь стандартную (пустую) реализацию Dispose ()
тогда и, возможно, шаблон финализатора / Dispose (bool), то есть
void IDisposable.Dispose() { Dispose(true); GC.SuppressFinalize(this); }
protected virtual void Dispose(bool disposing) {}
~BaseType() {Dispose(false);}
Если вы знаете, что некоторые реализации ISomeInterface требуют удаления, тогда интерфейс должен наследовать IDisposable, даже если конкретные реализации интерфейса не имеют ничего, что нужно было бы удалить.
Например, в BCL, IDataReader реализует IDisposable, хотя можно, конечно, представить себе реализации считывателя данных, у которых нет внешних ресурсов, которые необходимо удалить.
Это зависит от вашего интерфейса, но я бы предпочел №2. Если у вас есть две реализации ISomeInterface
и только одна требует удаления, то есть вероятность, что вам потребуется провести рефакторинг.
Обычно, когда вы привязываетесь к интерфейсу, лучше, чтобы этот интерфейс наследовал IDisposable
, а не базовый класс; если ваш интерфейс не наследует IDisposable
, вы должны преобразовать его в IDisposable
, чтобы избавиться от объекта, и это создает риск InvalidCast ...
Если вы хотите, чтобы весь ваш код имел дело с ISomeInterfaces в целом, то да, все они должны быть одноразовыми.
Если нет, то код, который создает FirstClass, должен его удалить:
using (FirstClass foo = new FirstClass()) {
someObjectThatWantsISomeInterface.Act(foo);
}
в противном случае вы всегда можете использовать что-то вроде этот метод расширения:
public static void DisposeIfPossible(this object o) {
IDisposable disp = o as IDisposable;
if (disp != null)
disp.Dispose();
}
// ...
someObject.DisposeIfPossible(); // extension method on object
Я также должен упомянуть, что я бы предпочел подход базового класса шаблона для этого. Я написал об этом в блоге о правильном изготовлении одноразовых вещей.
Мой совет - переходите к корню, а не напрямую к конкретному классу. Пункт 2 относится к корню, и вы руководствуетесь каким-то контрактом с FirstClass. Если вы знаете, что классы должны реализовывать какой-то интерфейс, тогда вы хотите убедиться, что интерфейс, который они подписывают в контракте, iwth наследует IDisposable