1 2
Паттерн Dispose и финализатор в избранное  новое горячее всё    подписка   модер. 
От: VladD2 админwww.k-press.ru/cs
Дата: 05.09.11 17:09
У меня тут возник почти философский вопрос...

Нужно (ну, хотя бы в каких-то случаях), при реализации паттерна Dispose, реализовывать финализатор, если объект не содержит ссылок на неуправляемые ресурсы.

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

Наличие финализатора автоматически продвигает объекты в седующее поколение. Плюс увеличение очереди финализации не ускоряет производительности. Так не лучше ли не реализовывать финализатор для объектов не управляющих неуправляемыми ресурсами?

Это, конечно, приводит к тому, что придется объявлять финализатор в классах-наследниках таких "безфинализаторных" объектах реализующих паттерн Dispose. Но ведь это как раз не проблема.

В общем, вопроса как такового нет. Просто хочется получить конструктивную критику моих размышлений. Прав ли я? И, если не прав, то в чем я заблуждаюсь?
Вышел Nemerle 1.0


Все что нас не убивает, потом сильно об этом жалеет :).
Re: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: G2 
Дата: 05.09.11 17:49
Здравствуйте, VladD2, Вы писали:
VD>Нужно (ну, хотя бы в каких-то случаях), при реализации паттерна Dispose, реализовывать финализатор, если объект не содержит ссылок на неуправляемые ресурсы.

AFAIK, стратегия такая, что реализовывать Finalize и Dispose нужно, только если сам тип должен освободить unmanaged ресурсы, которые он сам же и выделял. Если объект выделяет память только под disposable managed ресурсы, то реализовывать IDisposable не нужно.
Улыбаемся и машем :-)
Re: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: G2 
Дата: 05.09.11 17:52
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>У меня тут возник почти философский вопрос...


VD>Нужно (ну, хотя бы в каких-то случаях), при реализации паттерна Dispose, реализовывать финализатор, если объект не содержит ссылок на неуправляемые ресурсы.


AFAIK, стратегия такая, что реализовывать Finalize и Dispose нужно, только если сам тип должен освободить unmanaged ресурсы, которые он сам же и выделял. Если объект выделяет память только под disposable managed ресурсы, то реализовывать Finalize не нужно.
Улыбаемся и машем :-)
Re: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: Lloyd 
Дата: 05.09.11 17:58
Оценка:48 (1) +1
Здравствуйте, VladD2, Вы писали:

VD>В общем, вопроса как такового нет. Просто хочется получить конструктивную критику моих размышлений. Прав ли я? И, если не прав, то в чем я заблуждаюсь?


Прав. Вот комментарий из примера в msdn:

// This type does not need a finalizer because it does not
// directly create a native resource like a file handle
// or memory in the unmanaged heap.

http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx
Re[2]: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: VladD2 админwww.k-press.ru/cs
Дата: 05.09.11 18:12
Здравствуйте, G2, Вы писали:

G2>AFAIK, стратегия такая, что реализовывать Finalize и Dispose нужно, только если сам тип должен освободить unmanaged ресурсы, которые он сам же и выделял. Если объект выделяет память только под disposable managed ресурсы, то реализовывать IDisposable не нужно.


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

Вот на счет Finalize согласен.
Вышел Nemerle 1.0


Все что нас не убивает, потом сильно об этом жалеет :).
Re[2]: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: VladD2 админwww.k-press.ru/cs
Дата: 05.09.11 18:14
Здравствуйте, Lloyd, Вы писали:

L>Прав. Вот комментарий из примера в msdn:

L>

L>// This type does not need a finalizer because it does not
L>// directly create a native resource like a file handle
L>// or memory in the unmanaged heap.

L>http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx

Больно убого (и по разному) они его описывают. Есть прмеры, где финализатор запихивается в базовый класс, и стало быть, поддерживаются даже, если анменеджед-ресурсов нет (просто ради того что они могут появиться в наследнике).
Вышел Nemerle 1.0


Все что нас не убивает, потом сильно об этом жалеет :).
Re: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: hardcase 
Дата: 05.09.11 18:16
Оценка:10 (2)
Здравствуйте, VladD2, Вы писали:

VD>У меня тут возник почти философский вопрос...


Возможно эта статья поможет.
/* иЗвиНите зА неРовнЫй поЧерК */
Re: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: TK модераторblogs.gotdotnet.ru
Дата: 05.09.11 18:18
Здравствуйте, VladD2, Вы писали:

VD>Нужно (ну, хотя бы в каких-то случаях), при реализации паттерна Dispose, реализовывать финализатор, если объект не содержит ссылок на неуправляемые ресурсы.


Статья на MSDN еще со времен первого фреймворка. Для неуправляемых ресурсов есть SafeHandle.

VD>В общем, вопроса как такового нет. Просто хочется получить конструктивную критику моих размышлений. Прав ли я? И, если не прав, то в чем я заблуждаюсь?


По хорошему, у объекта с финализатором в конструкторе должен быть GC.SuppressFinalize(this), а реальная регистрация в очереди должна быть в методе типа SetResource(...)
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[3]: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: Lloyd 
Дата: 05.09.11 18:18
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Не верная, у тебя, стратегия. Dispose реализуется для освобождения любых ресурсов. И об этом везде, и довольно доходчиво, сказано. Объект может банально отписываться от событий или закрывать несколько ресурсов которыми он владеет.


Он поправился ниже.
Re[2]: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: TK модераторblogs.gotdotnet.ru
Дата: 05.09.11 18:26
Оценка:2 (1)
Здравствуйте, G2, Вы писали:

G2>AFAIK, стратегия такая, что реализовывать Finalize и Dispose нужно, только если сам тип должен освободить unmanaged ресурсы, которые он сам же и выделял. Если объект выделяет память только под disposable managed ресурсы, то реализовывать Finalize не нужно.


CriticalFinilizerObject есть одно из следствий того, что в финализаторах бывает нужно "освобождать" другие managed объекты. Типичный пример — буферизированный поток. Никаких unmanaged ресурсов у него может и не быть но, при этом может потребоваться сбросить буфер даже в случае "потери" объекта.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: rm822 
Дата: 06.09.11 05:14
VD>Нужно (ну, хотя бы в каких-то случаях), при реализации паттерна Dispose, реализовывать финализатор, если объект не содержит ссылок на неуправляемые ресурсы.
VD>Ведь, в таком случае, все ресурсы имеют свои финализаторы и они один фиг будут вызваны.
Да — нужно, нет не будут(по крайней мере не будут вызываны вовремя).
class MyForm
{
  MyControl m_ctrl; //
    MyForm()
    {
       ....
       m_ctrl.SubscribeOnWinlogonEvents;
         ....
    }
}


где-то в недрах системы есть синглтон реализующий подписку на WinLogon события.
после вызова m_ctrl.SubscribeOnWinlogonEvents, остается ссылка на m_ctrl которая не будет освобождена.
Рвать эту связь придется и в MyForm.Dispose и в MyForm.Finalize
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: TK модераторblogs.gotdotnet.ru
Дата: 06.09.11 05:17
Здравствуйте, rm822, Вы писали:

R>где-то в недрах системы есть синглтон реализующий подписку на WinLogon события.

R>после вызова m_ctrl.SubscribeOnWinlogonEvents, остается ссылка на m_ctrl которая не будет освобождена.
R>Рвать эту связь придется и в MyForm.Dispose и в MyForm.Finalize

В чем смысл разрывания связи в Finalize?
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[3]: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: rm822 
Дата: 06.09.11 05:38
TK>В чем смысл разрывания связи в Finalize?
представь что MyForm — популярная формочка, которой пользуется еще 30 человек в компании. Кто-нибудь обязательно не напишет using
мы не можем гарантировать вызов MyForm.Dispose, а раз не можем — придется подстраховаться в Finalize, иначе будет утечка ресурсов
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: SergeyT. rsdnhttp://sergeyteplyakov.blogspot.com/
Дата: 06.09.11 06:58
Оценка:74 (3) +2
Здравствуйте, VladD2, Вы писали:

VD>У меня тут возник почти философский вопрос...


VD>Нужно (ну, хотя бы в каких-то случаях), при реализации паттерна Dispose, реализовывать финализатор, если объект не содержит ссылок на неуправляемые ресурсы.


VD>В общем, вопроса как такового нет. Просто хочется получить конструктивную критику моих размышлений. Прав ли я? И, если не прав, то в чем я заблуждаюсь?


ИМХО следующее. Камрад Рихтер, как и некоторые примеры MSDN-а приводят не самые лучшие примеры.
Каноническая реализация Disposable-паттерна следующая (это все знают, но так обсуждать легче):

class Boo : IDisposable
{
  // Если класс содержит неуправляемые ресурсы, то объявляем финализатор
  /*
  ~Boo()
  {
     Dispose(false);
  }
  */
  public void Dispose()
  {
     Dispose(true);
     // даже если текущий класс не содержит финализатор, вызываем метод GC.SuppressFinalizer
     // на тот случай, если у наследников появятся неуправляемые ресурсы
     GC.SuppressFinalize(this);
  }
  
  protected virtual void Dispose(bool disposing)
  {
     // Повторный вызов Dispose игнорируем, т.е. сознательно не вводим
     // никаких флагов типа disposed, поскольку они не влияют на это обсуждение
     if (disposing)
     {
        // Очищаем управляемые и неуправляемые ресурсы
     }
     else
     {
        // Очищаем только неуправляемые ресурсы, если они у нас есть
     }
  }
}


Идея этого паттерна сводится к тому, что у нас могут появится наследники, у который появятся голые неуправляемые ресурсы, поэтому многие прикладные программисты его слепо копи-пастят, а иногда, не понимая четко все его принципы оставляют финализатор, даже есть у текущего класса нет неуправляемых ресурсов. При этом ветка else в методе Dispose(bool) всегда остается пустой.

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

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

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

Отсюда ИМО, оставить финализаторы только wrapper-ам, реализующим RAII, остальным юзать только управляемые ресурсы, а посему — забить на финализаторы.
Re: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: Sinix 
Дата: 06.09.11 07:03
Здравствуйте, VladD2, Вы писали:

VD>Нужно (ну, хотя бы в каких-то случаях), при реализации паттерна Dispose, реализовывать финализатор, если объект не содержит ссылок на неуправляемые ресурсы.


По-моему, только в очень редких случаях. Сам использовал пару раз для аварийного удаления временных файлов, но там ситуация была из разряда "жить захочешь — и не так раскорячишься".
Re[2]: «Disposable Design Principle» vs. «IDisposable code p в избранное  новое    модер. 
От: Qbit86http://bik-top.livejournal.com
Дата: 06.09.11 07:14
Здравствуйте, SergeyT., Вы писали:

ST>Отсюда ИМО, оставить финализаторы только wrapper-ам, реализующим RAII, остальным юзать только управляемые ресурсы, а посему — забить на финализаторы.


По ссылке
Автор: hardcase
Дата: 05.09.11
hardcase это и написано. Там ещё всякое интересное написано, про Constrained Execution Region, GC.KeepAlive и SafeHandle.
Глаза у меня добрые, но рубашка — смирительная!
Re[4]: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: TK модераторblogs.gotdotnet.ru
Дата: 06.09.11 08:20
Здравствуйте, rm822, Вы писали:

R>представь что MyForm — популярная формочка, которой пользуется еще 30 человек в компании. Кто-нибудь обязательно не напишет using

R>мы не можем гарантировать вызов MyForm.Dispose, а раз не можем — придется подстраховаться в Finalize, иначе будет утечка ресурсов

Вы точно правильно себе представляете что такое форма и в какой момент вызывается Finalize?
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[5]: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: rm822 
Дата: 06.09.11 08:50
Оценка:1 (1) +1
TK>Вы точно правильно себе представляете что такое форма и в какой момент вызывается Finalize?
да. Если есть что сказать — говори прямо, а не ходи вокруг да около с неуместными намеками на некомпетентность собеседника.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: Neco 
Дата: 06.09.11 08:53
Здравствуйте, VladD2, Вы писали:

VD>Это, конечно, приводит к тому, что придется объявлять финализатор в классах-наследниках таких "безфинализаторных" объектах реализующих паттерн Dispose. Но ведь это как раз не проблема.

но это ведь может стать проблемой — пользователь-программист должен не забыть объявить финализатор.
наличие финализатора в базовом классе делает неправильное использование менее вероятным, мне кажется. а то переопределит Dispose и пока (я, например, так бы и поступил).

кстати, а какие примеры реальной необходимости объявлять IDisposable при отсутствии неуправляемых ресурсов? Например, тот же TextReader зачем надо было делать IDisposable? Разве это не ответственность того, кто создаёт реально Disposable наследника — вызывать Dispose и т.п.? значит он тип должен знать?
всю ночь не ем, весь день не сплю — устаю
Re[6]: Паттерн Dispose и финализатор в избранное  новое    модер. 
От: TK модераторblogs.gotdotnet.ru
Дата: 06.09.11 09:03
Оценка: +1
Здравствуйте, rm822, Вы писали:

TK>>Вы точно правильно себе представляете что такое форма и в какой момент вызывается Finalize?

R>да. Если есть что сказать — говори прямо, а не ходи вокруг да около с неуместными намеками на некомпетентность собеседника.

Какие намеки? Вы лучше расскажите зачем у формы есть поле m_ctrl которое как-бы контрол но, при этом на форме он не лежит и никак с ней не взаимодействует?
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
1 2