Я выхожу на конечность, но ... большинству людей не не нужен полноценный образец избавления. Он спроектирован так, чтобы иметь прямой доступ к неуправляемым ресурсам (обычно через IntPtr
) и к наследованию. В большинстве случаев ни один из них на самом деле не требуется.
Если вы просто держите ссылку на что-то еще, что реализует IDisposable
, вам почти наверняка не нужен финализатор - все, что содержит ресурс, непосредственно отвечает за работу с этим. Вы можете обойтись чем-то вроде этого:
public sealed class Foo : IDisposable
{
private bool disposed;
private FileStream stream;
// Other code
public void Dispose()
{
if (disposed)
{
return;
}
stream.Dispose();
disposed = true;
}
}
Обратите внимание, что этот не поточно-ориентированный, но это, вероятно, не будет проблемой.
Не нужно беспокоиться о возможности подклассов, напрямую удерживающих ресурсы, вам не нужно подавлять финализатор (потому что его нет) - и вам не нужно предоставлять способ подкласса настраивать удаление или. Жизнь проще без наследства.
Если вам нужно разрешить неконтролируемое наследование (т. Е. Вы не готовы поспорить, что у подклассов будут очень специфические потребности), тогда вам нужно перейти на полную схему.
Обратите внимание, что в SafeHandle
из .NET 2.0 еще реже требуется собственный финализатор, чем в .NET 1.1.
Чтобы ответить на вопрос о том, почему в первую очередь существует флаг disposing
: если вы работаете в финализаторе, другие объекты, на которые вы ссылаетесь, возможно, уже были завершены. Вы должны позволить им очистить себя, и вы должны очищать только ресурсы, которые непосредственно принадлежат.