2016-08-03 6 views
-1

В то время как Dispose Pattern широко обсуждается в Интернете и SOF, я не мог найти ресурс, который отвечает на мои вопросы.Метод Dispose (bool) необходим, если финализатор не реализован?

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


Я видел много классов, которые (вслепую?) Реализуют шаблон размещения без реализации финализатора.

MSDN article on Dispose Pattern говорит:

Логический параметр указывает Утилизация был ли метод вызывается из реализации IDisposable.Dispose или из финализаторе. Реализация Dispose (bool) должна проверять параметр перед доступом к другим ссылочным объектам (например, поле ресурса в предыдущем примере). К таким объектам следует обращаться только при вызове метода из реализации IDisposable.Dispose (когда параметр утилизации равен true). Если метод вызывается из финализатора (удаление ложно), другие объекты не должны быть доступны. Причина в том, что объекты завершаются в непредсказуемом порядке, и поэтому они или любая их зависимость могут уже быть завершены.

В соответствии с тем, что я понимаю, GC вызывает метод finalizer (если он реализован), который в свою очередь должен вызывать метод Dispose (bool) с параметром как false.

Мой первый вопрос: если класс не реализует финализатор, то ли Dispose (bool) когда-либо вызываются с параметром как false? (например, что-то в CLR, которое я не обнаружил)

Я понимаю, что Dispose (bool) можно использовать, чтобы убедиться, что объекты расположены только один раз.

Таким образом, мой второй вопрос: если классу не нужно реализовывать финализатор, то может ли он просто реализовать метод Dispose, как показано ниже?

private bool objectDisposed; 
public void Dispose() 
{ 
    if (!objectDisposed) 
    { 
     // Release/dispose managed resources 
     // ... 
     // ... 

     objectDisposed = true; 
    } 
} 
+0

[Эта обширная статья о Dispose] (https://web.archive.org/web/20051122090032/http:/ /www.bluebytesoftware.com/blog/PermaLink.aspx?guid=88e62cdf-5919-4ac7-bc33-20c06ae539ae) ответит на все ваши вопросы (отредактируйте: ссылка на обратную версию, так как форматирование там написано) – stuartd

+0

[Очень важно для этого вопрос.. .] (http://stackoverflow.com/questions/11024336/why-does-sealed-affect-the-implementation-of-idisposable) – spender

+0

спасибо, ребята, я уже прочитал первый. – Menol

ответ

1

Мой первый вопрос, если класс не реализует финализации то делает Dispose (BOOL) когда-нибудь вызывается с параметром как ложь? (Например что-то в CLR, что я не встречал)

NO

Поэтому мой второй вопрос, если класс не нужно реализовать финализации, то может это просто реализовать метод Dispose, например, ?

Я бы не стал, но мог. Если вы это сделаете, вы будете изобретать шаблон IDisposable, если этот класс будет расширен. Как указано в комментарии HansPassant, шаблоны IDisposable очень удобны, если существуют производные классы. Я предпочел бы следовать примеру.

Базовый класс

using System; 

class BaseClass : IDisposable 
{ 
    // Flag: Has Dispose already been called? 
    bool disposed = false; 

    // Public implementation of Dispose pattern callable by consumers. 
    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this);   
    } 

    // Protected implementation of Dispose pattern. 
    protected virtual void Dispose(bool disposing) 
    { 
     if (disposed) 
     return; 

     if (disposing) { 
     // Free any other managed objects here. 
     // 
     } 

     // Free any unmanaged objects here. 
     // 
     disposed = true; 
    } 

    // Only if there are unmanaged resources. 
    ~BaseClass() 
    { 
     Dispose(false); 
    } 
} 

производный класс

using System; 

class DerivedClass : BaseClass 
{ 
    // Flag: Has Dispose already been called? 
    bool disposed = false; 

    // Protected implementation of Dispose pattern. 
    protected override void Dispose(bool disposing) 
    { 
     if (disposed) 
     return; 

     if (disposing) { 
     // Free any other managed objects here. 
     // 
     } 

     // Free any unmanaged objects here. 
     // 
     disposed = true; 

     // Call the base class implementation. 
     base.Dispose(disposing); 
    } 

    // Only if there are unmanaged resources. 
    ~DerivedClass() 
    { 
     Dispose(false); 
    } 
} 
+0

Либо это, либо сделать класс герметичным, чтобы он не мог быть расширен. –

+0

Нам действительно нужно избавиться от этой бессмыслицы, этот ответ не помогает нам туда добраться. Новое правило: если вы не запечатываете класс, тогда ** всегда ** сделайте метод Dispose() виртуальным. Стандартное правило в C++ btw. –