Re[3]: Правила использования финалайзеров [blog]
От: Sinclair Россия https://github.com/evilguest/
Дата: 20.01.06 10:30
Оценка: +3
Здравствуйте, mihailik, Вы писали:

GZ>>Ага, и выучить Dispose Pattern назубок. Сейчас как раз наблюдаю крутую очистку в финалайзере.


M>Хм, статья в MSDN сильно страдает теми же тараканами:


M>Во-первых, название Design Pattern сразу обманывает читателя.


M>Во-вторых, в тексте попросту НЕ ОБЪЯСНЯЕТСЯ, как Dispose связано с Finalize. Поэтому подразумевается, что это причинно-следственная связь. То есть, Design Pattern ТРЕБУЕТ Finalize? Ересь!

Вообще, я до сих пор не могу понять этих приплясываний с bool параметром.
почему нельзя сделать вот так:
public class BaseResource: IDisposable
{
  private bool disposed = false;
  public void Dispose()
  {
    if (!disposed)
        {
      DisposeManaged();
            DisposeUnmanaged();
            disposed = true;
      GC.SuppressFinalize(this);
        }
  }

  // Dispose managed resources.
  protected virtual void DisposeManaged()
  {
    Components.Dispose();
  }
  // Release unmanaged resources. 
    protected virtual void DisposeUnmanaged()
    {
        CloseHandle(handle);
        handle = IntPtr.Zero;
  }

   // Do not provide destructors in types derived from this class.
   ~BaseResource()      
   {
      DisposeUnmanaged(false);
   }

   public void DoSomething()
   {
      if(this.disposed)
      {
         throw new ObjectDisposedException();
      }
   }
}

// Design pattern for a derived class.
// Note that this derived class inherently implements the 
// IDisposable interface because it is implemented in the base class.
public class MyResourceWrapper: BaseResource
{
   // A managed resource that you add in this derived class.
   private ManagedResource addedManaged;
   // A native unmanaged resource that you add in this derived class.
   private NativeResource addedNative;
   private bool disposed = false;

  // Constructor for this object.
   public MyResourceWrapper()
   {
      // Insert appropriate constructor code here.
   }

  protected override void DisposeManaged()
  {
        addedManaged.Dispose();         
        base.DisposeManaged();
    }
    protected override void DisposeUnmanaged()
    {
        CloseHandle(addedNative);
        base.DisposeUnmanaged();
  }
}

По-моему, так гораздо яснее, и труднее сделать ошибку. Можно еще подумать на тему иерархии классов, где не все обязаны иметь оба типа ресурсов, нуждающихся в финализации.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: Правила использования финалайзеров [blog]
От: Аноним  
Дата: 22.01.06 18:24
Оценка: 42 (2)
Переписка из блога.

mihailik >>>>Многие наши программисты предпочитают что-то слащаво-подростковое, например Рихтера. Классный дядька Рихтер, успешный. Но есть у него много методических провалов.

Gollum >>Ну и "борюсь с Рихтером" — это немного смешно.


Согласен, звучит самоутверждающе. Но не будем делать скорополительных выводов, а лучше посмотрим, возможно, для этого действительно есть определенные основания... Дабы исключить искажение смыла переводчиками (а ручаться можно только за себя), я взял и перечитал английское издание книги Applied Microsoft .NET Framework Programming. Вот то, что я понял, и что мне запомнилось.:

Каждый объект, который работает с неуправляемыми ресурсами (например, с файлами или сокетами), должен поддерживать финализацию (finalization). Финализация позволяет ресурсу прибрать за собой во время сборки мусора. Если объект содержит метод Finalize, то он вызывается сборщиком мусора. Если тип, который работает с неуправляемыми ресурсами, не реализует метод Finalize, то это приведет к утечкам памяти. Ресурсы не будут освобождены покуда не завершится поток, их использовавший.

Переписка из блога.

>>Финализатор имеет смысл только если непосредственно ваш класс хранит в себе Handle внешнего ресурса (за редчайшим исключением).

Очевидно, что именно это и говорит нам Рихтер. Процитирую свой перевод: "Каждый объект, который работает с неуправляемыми ресурсами [skip], должен поддерживать финализацию [skip]." У меня нету сейчас под рукой русского издания, но в этом месте если и возникает разночтение, то только по вине этого самого русского издания. В английском варианте лично для меня тут все достаточно прозрачно.

Тут, между прочим, даже сам Рихтер оговаривается по поводу метода Finalize(), мол, девелоперы не тем боком этот метод юзают, поэтому команда разработчиков компилятора языка C# подумала-подумала, и сделала потенциально опасный код вне закона. Вопрос: это защита от дурака, или от Рихтера? Причем, Рихтер опять же оговаривается, что, в общем-то зря они синтаксис деструктора C# слизали с С++, ведь это только вгоняет сишников в ступор. Опять предупреждение, и не от кого бы то ни было, а от самого Рихтера. А ученики, похоже, просто прохлопали ушами этот момент. Читаем дальше.


Если вы знакомы с С++, то сразу заметите, что синтаксис деструктора (этот метод так и называется в спецификации) совпадает с таковым в С++. Тем не менее, Finalize работает совсем не так, как деструктор в С++. ПРИ НАПИСАНИИ СВОЕГО ТИПА ЛУЧШЕ ВОЗДЕРЖАТЬСЯ ОТ FINALIZE.

Дальше можно уже и не комментировать (но я на этом месте не остановился). Я примерил на себя костюм "разрушителей мифов" с канала Discovery, и судя по всему у меня это неплохо получилось. Ну что, миф разрушен?


В _очередной_ раз видим необоснованный выпад, и кстати, не только в сторону Джеффри Рихтера...


Переписка из блога.

>>Они похожи на деструкторы C++
>>— в результате, программисты пишут и думают себе что-то одно, а получается ОЧЕНЬ другое

Я не знаю, о чем думают программисты, когда пишут свой код, но явно не о Рихтере... И приведенный выше фрагмент в моей интерпретации это полностью доказывает.

>>Они вызываются в нефиксированный момент времени
>>— при отладке в условиях A мы видим одно поведение, а при реальной работе в условиях B имеем совсем другое

Именно об этом нам и пишет Рихтер. Кратко но _доходчиво_ разъясняя технические аспекты. Вот этот отрывок (это мой литературный перевод, можете cверить с "настоящим" русским изданием, вполне возможно, там содержатся ошибки, которые и ведут к оказиям):

"
Примечание.
В таблице 19-1 обратите внимание, что на аргумент arg1 нашего метода больше никто не ссылается после инструкций процессора со смещением 0x00000020. Это значит, что объект arg1 помечается как "пригодный для сборки в любое время" после выполнения этих инструкций (предполагается, что в приложении больше нет корневых элементов, которые ссылаются на этот объект). Другими словами, как только объект становится недостижимым [чтобы понять смысл этой фразы, нужно читнуть пару абзацев выше, но эти потуги я уже возложу на плечи наших "учеников"], он превращается в кандидата на сборку, поэтому не гарантируется, что объекты будут жить на протяжении всего времени выполнения метода.
[Дальше пошло самое вкусное.]
Одако, когда приложение выполняется через отладчик, или когда сборка помечена атрибутом System.Diagnostics.DebuggableAttribute с параметром isJITOptimizerDisabled выставленным в true, компилятор JIT продлевает время жизни всех переменных (будь то типы, передающиеся по значению или по ссылке) до окончания их области видимости, что в большинстве случаев означает конец самого метода. (Между прочим, компилятор C#, при использовании ключа /debug в командной строке, помечает сборку атрибутом DebuggerAttribute, устанавливая параметр isJITOptimizerDisabled в true.) Это расширение предотвращает сборщика мусора от сборки ссылочных типов во время выполнения кода в данной области видимости, что полезно при отладке. Было бы совсем неуместно, если бы вы вызвали метод объекта, получили неправильный результат, а затем не смогли бы даже взглянуть на этот объект!
"

Рихтер сказал один в один по писаному... Или наоборот.


P.S. Рихтер, как известно, на короткой ноге с Microsoft. И я очень сильно сомневаюсь, что кто-то намного лучше самих майкрософтовцев знает, как пользоваться их продуктами. Поэтому бороться если и надо, то не с Рихтером, а с гореучениками, которые не в состоянии уловить мысль человека до конца. Повышать, так сказать, уровень базовых знаний (и в руки Рихтера не давать!). А то человек оперирует таким понятиями, как "функция memcpy", "регистр процессора", хотя для многих "начинающих" это звучит как заклинание. Тогда о каком чтении Рихтера может идти речь? Нужно брать что-то более научно-популярное... Хотя мне кажется, что если читатель толковый, то, дочитав до незнакомого слова, полезет в нет и разберется, что к чему. Это даже способствует повышению уровня своего развития. И не только в сторону освоения .NET. Так что IMHO рано-то Рихтера на свалку истории списывать... Превзойти своего учителя это похвально, вот только не нужно унижать его талант.

Alexander__S >>Финлазиторы плохи, спору нет. Но за все надо платить, в том числе и за GC.

Они не плохи. Просто ко всему нужно подходить с головой. Сначала работает голова, и только потом руки. Тогда все будет путем.

[[url=http://www.gotdotnet.ru/DotNet/FAQ/OfflineFAQ/236958.aspx]Offline FAQ[/url]] [1.01]
2 min @ 56.6 kbps


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re: Правила использования финалайзеров [blog]
От: R0man Украина  
Дата: 16.01.06 19:30
Оценка: +2
Здравствуйте, mihailik, Вы писали:

M>Как известно, .NET Framework предоставляет объектам перед уничтожением "последнее желание", Finalize. К несчастью, многие плохо понимают чем такие вещи чреваты.


M><b>Финализаторы и деструкторы в C#</b>


M>Правила:

M>1. Финализатор имеет смысл только если непосредственно ваш класс хранит в себе Handle внешнего ресурса (за редчайшим исключением)

M>2. Если вас потянуло на Finalize, постарайтесь переключиться на IDisposable, это и безвредно, и полезно


M>3. При переопределении метода Dispose(bool) выполняйте очистительные действия только если disposing==true (в противном случае очистку сделают и без вас)


А в чем заключаются провалы в методологии Рихтера, на Ваш вгляд, в контексте моделей особождения ресурсов?
Re[4]: Правила использования финалайзеров [blog]
От: Воронков Василий Россия  
Дата: 17.01.06 15:40
Оценка: :))
Здравствуйте, R0man, Вы писали:

Может вы разные издания читаете?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Правила использования финалайзеров [blog]
От: RegisteredUser  
Дата: 25.01.06 05:49
Оценка: 22 (1)
Здравствуйте, mihailik, Вы писали:

M>Методологически правильно:

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

Тем самым можно усугубить проблему. Запретный плод сладок — будут финалайзить тайно, когда никто не видит... Хотя сублимировать в сторону IDisposable сии постыдные желания пофинализировать — есть намерение безусловно благое.
Правила использования финалайзеров [blog]
От: mihailik Украина  
Дата: 16.01.06 17:37
Оценка: 6 (1)
Как известно, .NET Framework предоставляет объектам перед уничтожением "последнее желание", Finalize. К несчастью, многие плохо понимают чем такие вещи чреваты.

<b>Финализаторы и деструкторы в C#</b>

Правила:
1. Финализатор имеет смысл только если непосредственно ваш класс хранит в себе Handle внешнего ресурса (за редчайшим исключением)

2. Если вас потянуло на Finalize, постарайтесь переключиться на IDisposable, это и безвредно, и полезно

3. При переопределении метода Dispose(bool) выполняйте очистительные действия только если disposing==true (в противном случае очистку сделают и без вас)

30.01.06 00:08: Перенесено из '.NET'
Re[20]: Правила использования финалайзеров [blog]
От: TK Лес кывт.рф
Дата: 25.01.06 08:29
Оценка: 6 (1)
Hello, "Sinclair"
>
> TK>т.е. один if заменили на три метода, поле и свойство?
> Поле уже было. Свойство пришлось ввести для того, чтобы наследники
> получили к нему доступ. В оригинальном примере его не было, зато был бред
> в виде дополнительного поля. Что открывает замечательный простор по его
> сбросу обратно в false, рассогласованию состояний этих полей и прочему
> сабантую.

Тут сразу вопрос. А это поле вообще в базовой реализации нужно? Не
получается, что это я в трех книжках прочел, значит — так правильно?

>

Перегрузите метод DisposeManaged() в том случае, если ваш объект
> владеет другими объектами, реализующими IDisposable, и вызовите их
> Dispose().
> Перегрузите метод DisposeUnmanaged() в том случае, если ваш объект владеет
> какими-либо неуправляемыми ресурсами.

> Всё. Конец цытаты.

т.е. порядок вызова DisposeUnmanaged / DisposeManaged не специфицирован?
рассмотрим ситуацию. есть объект под названием Dialogue который
инкапсулирует в себе некий диалог работы с каналом (unmanaged ресурс). При
вызове Dispose нам надо корректно завершить диалог (сказать что я
пользователь (информация о пользователе это managed ресурс) такой-то работу
завершаю). Соответственно вопрос: как надежно завершить работу в ситуации
когда порядок вызовов DisposeManaged / DisposeUnmanaged не специфицирован? В
DisposeUnmanaged этого по идее сделать нельзя т.к. managed ресурсы уже могут
быть недоступны. Как это сделать из DisposeManaged тоже не ясно т.к.
реализация может вызвать DisposeUnmanaged раньше. Можешь как-то прояснить
данный аспект в своем описании?

>>> Если не задумываться над ситуацией с финализатором, то все вообще

>>> просто,
>>> как угол дома: меняем местами вызовы DisposeManaged и
>>> DisposeUnmanaged().
>
> TK>т.е. опять меняем базовый класс... и это называется дизайн?
> Это называется поиск дизайна.

Ну ок. Уже второй день пошел как мы это обсуждаем. Можно зафиксировать
какое-то решение?

> Что это такое? Что означает ManagedAllocate(), что делает

> ManagedRelease()? Этот пример кода вообще не будет работать, т.к. некому
> вызвать Dispose. Если имелось в виду наследование этого класса от
> МС-примера, то объясни мне
> а) почему _managedArray не будет собран сборщиком мусора сам по себе, без
> наших усилий помешать ему делать его работу?
> б) что гарантирует нам корректную работу ManagedRelease() при вызове из
> финалайзера, когда нельзя полагаться на нефинализированность других
> объектов?
>

a. Ключевое слово это ПУЛ ОБЪЕКТОВ. Есть объекты безконтрольное
создание/уничтожение которых является достаточно накладной операцией.
Поэтому, в некоторых случаях, имеет смысл организовать пул подобных
объектов. При этом, для реализации такого пула задействовать какие либо
unmanaged ресурсы вовсе не обязательно.
б. Если ты не понял код, то давай его перепишем более понятно:

// Это примерный код. Просто, для прояснения ситуации.
class SomeManagedResource : IDisposable
{
    byte[] _managedResource;
    static byte[] _cache;

    public SomeManagedResource()
    {
        _managedResource = ManagedAllocate();
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        ManagedRelease(_managedResource);
        _managedResource = null;
    }

    ~SomeManagedResource()
    {
        Dispose(false);
    }

    static byte[] ManagedAllocate()
    {
        byte[] resource;

        if (_cache == null)
        {
            resource = new byte[VERY_BIG_ARRAY];
        }
        else
        {
            resource = _cache;
            _cache = null;
        }

        return resource;
    }

    static void ManagedRelease(byte[] resource)
    {
        _cache = resource;
    }
}


В данном случае, есть какие-то вопросы относительно корректной работы
ManagedRelease в финалайзере? В любом случае, вызов из финалайзера не
означает, что все внешние ссылки объекта порушены и ими нельзя пользоваться.
Это лишь означает то, что для внешних объектов уже мог быть вызван
финализатор. Но, если у объекта финализатора нет то им можно пользоваться
без каких либо ограничений.

Кстати, ты приведенный код понял? Можешь переписать его в рамках своего
паттерна?

На всякий случай проясню ситуацию с массивом. Сборщик мусора в первую
очередь оптимизирован для работы с набольшими объектами. При этом, объекты
большого размера (при желании можешь найти какого) создаются, скажем так, в
специальной области кучи, не подвергаются дефрагментации и их сбор
происходит только при полной сборке мусора (что, уже может быть накладной
операцией). т.е. если некоторый алгоритм переодически требует большие объемы
памяти то, лучше ими просто так не разбрасываться. Если конечно нет цели
постоянно нарываться на сборку мусора...

> TK>твой паттерн. Лично мне хотелось бы видеть какое то законченное

> решение.
> Мне бы тоже. Но у меня его нет. Есть решение от МС, которое я не понимаю.
> Я не пытаюсь научить тебя правильно программировать под дотнет. Я пытаюсь
> понять, зачем МС сделала такую странную реализацию, и можно ли сделать
> лучше.

Дался вам этот МС... Ты не допускаешь себе мысли, что никакого тайного
смысла в данном примере вообще нет? Такой же человек, как ты, сел и написал
первый, пришедший ему в голову код. Потом, этот код попал в MSDN. Я думаю,
что теперь, когда ему задают вопросы а почему он так сделал он тоже отвечает
"а было еще хуже", "поле уже было мы только свойство добавили", "не давите
на меня". Вот и вся тайна Предложенная реализация мне тоже кажется
несколько странной и в чем-то однобокой (use case я предложил. кроме ответа
"это все надумано" я ничего не вижу)... Поэтому и встает вопрос, а в чем
смысл смены "шила на мыло"? Вдруг, завтра колоть придется...
Posted via RSDN NNTP Server 2.0
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[16]: Правила использования финалайзеров [blog]
От: TK Лес кывт.рф
Дата: 24.01.06 10:02
Оценка: 1 (1)
Hello, "Sinclair"
>
> Далее, если тебе очень хочется трейсить ситуацию отсутствия своевременного
> вызова Disposе, то достаточно вставить трейс в финалайзер базового
> класса — ведь его вызов подавляется вызовом Dispose().
>

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

Кроме того, Mika уже написал свое замечание на тему того, что два раздельных
метода освобождения ресурса на какой-то момент оставляют объект в
несогласованном состоянии (ситуацию с финализатором мы пока в расчет не
берем т.к. это крайний случай и в нормальной ситуации все ресурсы
освобождаются по Dispose). Как будет разруливаться данная ситуация? Хотелось
бы каких нибудь комментариев (а еще лучше, пример кода.

Что касается дизайна в целом то, ситуация пока следующая:
  • Dispose Pattern: Один метод с одним аргументом
  • Dispose "Anti" Pattern: Два метода, поле, свойство, нетривиальный код
    (раз уж с первого раза написать не удалось) плюс очень похоже, что есть
    проблемы с покрытием существующих use cases (для примера возьмем трейс в
    наследнике)

    Тут как не крути, но по очкам "альтернативное" решение проигрывает сильнее
    некуда...
    Posted via RSDN NNTP Server 2.0
  • Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
    Re[2]: Правила использования финалайзеров [blog]
    От: mihailik Украина  
    Дата: 17.01.06 07:40
    Оценка: +1
    R>А в чем заключаются провалы в методологии Рихтера, на Ваш вгляд, в контексте моделей особождения ресурсов?

    Он очень много и увлекательно описывает финализаторы, не слишком заостряя внимание на том, что они
    а) сложны и небезопасны
    б) редко применимы

    Кроме того, в частности:

    По Рихтеру складывается впечатление, что Dispose КАК ПРАВИЛО реализуют одновременно с Finalize.

    Рихтер описывает шаблон правильного совмещения IDisposable и Finalizable, не говоря о том, в каких случаях он применим.

    * * *

    В итоге, программисты-новички начинают думать о Finalize как о средстве, нередко необходимом в собственных классах. Наподобие "если класс инкапсулирует ресурс, ему нужен Dispose и Finalize". НЕВЕРНО!!!

    Методологически правильно:
    — показать, что Finalize существует;
    — обяснить, зачем он существует;
    — быстро и внятно объяснить, что ему редко есть применение в собственных классах;
    — и тут же уводить разговор к Dispose.
    Re[12]: Правила использования финалайзеров [blog]
    От: TK Лес кывт.рф
    Дата: 23.01.06 13:10
    Оценка: +1
    Hello, "Merle"
    >
    > TK>Вот это у вас и хромает.
    > разьве?

    А ты приглядись

    > TK>да и все возможные варианты использования покрываются.

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

    Уже написал. Флаг disposing. Я хочу знать что происходит с объектом.

    Кроме того, как то у вас не продумана концепция инициализации объекта. Как
    будут создаваться manged/unmanaged русурсы. Хотелось бы некоторой симетрии в
    действиях. Это тоже будет два разных метода?
    Posted via RSDN NNTP Server 2.0
    Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
    Re[9]: Правила использования финалайзеров [blog]
    От: Mika Soukhov Stock#
    Дата: 23.01.06 13:28
    Оценка: +1
    Здравствуйте, TK, Вы писали:

    TK>Оно настолько очевидное, что более/менее правильный вариант удалось только с

    TK>третьего раза написать?
    TK>Кстати, если я хочу вызвать GC.ReRegisterForFinalize то, где это лучше
    TK>сделать, в DisposeUnmanaged? тоже, очевидное решение... Так же, действия в
    TK>финализаторе могут быть не обязательно связаны с unmanaged ресурсами...
    TK>Вобщем, название метода DisposeUnmanaged удачным назвать нельзя...

    Мне кажется, что основной проблемой разбиения на два метода будет являтся сценарий, когда неуправляемый ресурс освобождается в зависимости от состояния управляемого ресурса.

    public class WindowDescriptor
    {
      private Form _targetWindow;
      private int _descId;
    
      private static extern void CloseDescriptor(IntPtr hwnd, int descId);
    
      private static extern void CloseAllDescriptors(IntPtr hwnd);
    
      protected override void DisposeManaged()
      {
        _targetWindow.Dispose();
      }
    
      protected override void DisposeUnmanaged()
      {
        CloseDescriptor(_targetWindow.Handle, _descId); // тут вылезет все, что угодно, т.к. наше окно уже уничтожено.
      }
    }


    TK>Да и потом, как узнать в DisposeUnmanaged что именно происходит с объектом —

    TK>был вызван Dispose или запустился финализатор. Флаг завести?

    Я так понял, что два метода как раз инкапсулируют это поведение. В принципе, если эта информация очень нужна, то можно использовать два подхода.
    Re[15]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 24.01.06 07:58
    Оценка: +1
    Здравствуйте, TK, Вы писали:

    TK>Hello, "Sinclair"

    >>
    >> TK>Уже написал. Флаг disposing. Я хочу знать что происходит с объектом.
    >> Ты не мог бы привести пример кода, для которого это надо? Пример из MSDN полностью описывается парой методов.

    TK>
    TK>if (!disposing)
    TK>{
    TK>    Debug.WriteLine(...);
    TK>}
    TK>

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

    Вот пацаны из Редмонда предложили некоторую схему. Эта схема лично мне кажется непонятной и неустойчивой к ошибкам. Я не понимаю, зачем было делать метод, параметр которого задает место, откуда его вызвали. Я вообще считаю, что такие вещи крайне противопоказаны в OOD. Потому, что они затрудняют понимание сути метода.

    Я предложил заменить эту схему на эквивалентную ей, но с более внятной семантикой. Ты начинаешь докапываться до отсутствия параметра. Этот параметр — артефакт! Из примера МСДН никакой его самостоятельной ценности не видно. Он используется исключительно для того, чтобы понять, освобождать ли управляемые ресурсы. В той схеме, которая пришла в голову мне, необходимость освобождения управляемых ресурсов вопросов не вызывает — позвали у тебя DisposeManaged, вот и освобождай. DisposeManaged никогда не вызывается из финалайзера.

    Далее, если тебе очень хочется трейсить ситуацию отсутствия своевременного вызова Disposе, то достаточно вставить трейс в финалайзер базового класса — ведь его вызов подавляется вызовом Dispose().

    В общем, если у тебя есть чего сказать по делу — приводи примеры осмысленного кода, который иллюстрирует удобство паттерна от МС и неудобство моего. Вот, к примеру, я в жизни еще не сталкивался с необходимостью звать ReRegisterForFinalize(); у МС в примере и тени его нету. Покажи пример, где это надо, чтобы я понял, в чем собственно ущербность моей реализации. А рассказы про штаны через голову оставь для форума СВ.
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[25]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 01.02.06 14:21
    Оценка: +1
    Здравствуйте, Hacker_Delphi, Вы писали:
    H_D>Гм. при чем здесь архитектура?
    H_D>WeakReference для того, чтобы GC решал когда Cache надо "подчищать" — вроде бы нормально
    Это верно. Точнее, скажем так: WeakReference — для того, чтобы не удерживать объект.
    H_D>Hashtable для поиска по ID — тоже нормально...
    H_D>вычистить "мертвые" ссылки при "смерти" объекта — просто необходимо...
    А вот это уже заблуждение. Любое использование слабых ссылок предполагает возможность в любой момент потерять эту ссылку. Проектировать другим способом — нарываться на неприятности. Я вот не могу понять выигрыша от принудительного оповещения всех заинтересованных объектов о смерти слабой ссылки. Неужели вызов IsAlive при каждом обращении так дорог? При этом у тебя финалайзер выполняет работу порядка O() от количества слабых ссылок на умирающий объект. Что чревато нехорошими последствиями.
    H_D>что не так в архитектуре?
    H_D>Да, при более менее таком интенсивном использовании CacheHit составляет примерно 60 % — это при политике Service обслуживания GC.
    CacheHit, очевидно, никак не зависит от того, в какой момент происходит детектирование пропажи слабой ссылки. Если зависит — то косяк в архитектуре.
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[27]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 04.02.06 02:59
    Оценка: +1
    Здравствуйте, Hacker_Delphi, Вы писали:

    Избыточное цитировние удалено.
    H_D>Да, не зависит. А вот затраты на проверку, что ссылки IsAlive достаточно велики. После появления кода финалайзера, который чистит "дохлые" ссылки все заработало гораздо быстрее. И не надо говорить про Bad Design — вопрос в том, что так работает быстрее, а почему оно теоретически должно работать медленнее — меня не волнует.
    Миша, в таких случаях надо применять профайлер, а не теорию. Что за шаманство?
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re: Правила использования финалайзеров [blog]
    От: GlebZ Россия  
    Дата: 16.01.06 17:47
    Оценка:
    Здравствуйте, mihailik, Вы писали:

    Ага, и выучить Dispose Pattern назубок. Сейчас как раз наблюдаю крутую очистку в финалайзере.

    С уважением, Gleb.
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[2]: Правила использования финалайзеров [blog]
    От: mihailik Украина  
    Дата: 17.01.06 07:45
    Оценка:
    GZ>Ага, и выучить Dispose Pattern назубок. Сейчас как раз наблюдаю крутую очистку в финалайзере.

    Хм, статья в MSDN сильно страдает теми же тараканами:

    Во-первых, название Design Pattern сразу обманывает читателя.

    Во-вторых, в тексте попросту НЕ ОБЪЯСНЯЕТСЯ, как Dispose связано с Finalize. Поэтому подразумевается, что это причинно-следственная связь. То есть, Design Pattern ТРЕБУЕТ Finalize? Ересь!
    Re[3]: Правила использования финалайзеров [blog]
    От: R0man Украина  
    Дата: 17.01.06 07:46
    Оценка:
    Здравствуйте, mihailik, Вы писали:

    R>>А в чем заключаются провалы в методологии Рихтера, на Ваш вгляд, в контексте моделей особождения ресурсов?


    M>Он очень много и увлекательно описывает финализаторы, не слишком заостряя внимание на том, что они

    M>а) сложны и небезопасны
    M>б) редко применимы

    M>Кроме того, в частности:


    M>По Рихтеру складывается впечатление, что Dispose КАК ПРАВИЛО реализуют одновременно с Finalize.


    Ну... Каждый читает по-своему...

    M>Рихтер описывает шаблон правильного совмещения IDisposable и Finalizable, не говоря о том, в каких случаях он применим.


    M>* * *


    M>В итоге, программисты-новички начинают думать о Finalize как о средстве, нередко необходимом в собственных классах. Наподобие "если класс инкапсулирует ресурс, ему нужен Dispose и Finalize". НЕВЕРНО!!!


    M>Методологически правильно:

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

    Должен не согласиться, я как раз "новичек", прочитал недавно Рихтера, из выше сказанного в моей голове отразилось только указанное Вами в пункте "Методологически правильно". Может быть мне повезло!
    Re[4]: Правила использования финалайзеров [blog]
    От: mihailik Украина  
    Дата: 17.01.06 08:08
    Оценка:
    M>>— и тут же уводить разговор к Dispose.

    R>Должен не согласиться, я как раз "новичек", прочитал недавно Рихтера, из выше сказанного в моей голове отразилось только указанное Вами в пункте "Методологически правильно". Может быть мне повезло!


    Спасибо, Роман.
    Для меня это тоже полезный случай на заметку, хотя и нехарактерный.
    Re[4]: Правила использования финалайзеров [blog]
    От: Alexander__S  
    Дата: 20.01.06 21:01
    Оценка:
    Здравствуйте, Sinclair, Вы писали:

    Оверквотинг удален.

    S>По-моему, так гораздо яснее, и труднее сделать ошибку. Можно еще подумать на тему иерархии классов, где не все обязаны иметь оба типа ресурсов, нуждающихся в финализации.


    Не посчитайте за мелкие придирки, но хотелось бы прояснить некоторые вещи...

    Ну метод Dispose() c Finalize() сам по себе не связан никак. Связь определяет реалзиция программистом модели освобождения ресурсов. Я думаю, Вы именно это и имели в виду. Для полноты картины хотелось бы увидеть в листинге хотя бы псевдокод метода DisposeUnmanaged(bool disposing) . ИМХО, GC.SuppressFinalize(this); корректнее всатвить перед вызовами DisposeManaged(); DisposeUnmanaged();.

    Так в чем же все-таки существенное упрощение? Ну вводится локальная переменная вместо bool параметра, отдельные виртуальные методы очистки управляемых и неуправляемых ресурсов, которые классы-наследники должны переопределить при необходимости, и все это надо будет держать в голове и реализовывать программисту, так же, как и в случае стандартного паттерна.

    Все-таки то, что приводится в MSDN — паттерн, рекомендованный в общем случае, и, ИМХО, в этой связи сложно придумать что-либо более простое. Конечно же, то, что написано в MSDN, не является приказом, не подлежащим обсуждению, и ничто не мешает реализовать свою модель освобождения ресурсов, как в Вашем случае, и пользоваться ей. Единственное, что способствутет реализации программистом именно интерфейса IDisposable — это языковая поддержка (using, генерирующий блок try... finally с вызовом в последнем Dispose()), ну и само назначение этого интерфейса (реализованного во многих клссах FW) в контексте модели освобождения ресурсов.

    P.S.
    я бы добавил также lock в Dispose, и еще: throw new ObjectDisposedException(); компилироваться не будет
    Re: Правила использования финалайзеров [blog]
    От: Alexander__S  
    Дата: 20.01.06 21:35
    Оценка:
    Здравствуйте, mihailik, Вы писали:

    M><b>Финализаторы и деструкторы в C#</b>


    Финлазиторы плохи, спору нет. Но за все надо платить, в том числе и за GC.
    Re[5]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 22.01.06 09:38
    Оценка:
    Здравствуйте, Alexander__S, Вы писали:
    A__>Не посчитайте за мелкие придирки, но хотелось бы прояснить некоторые вещи...

    A__>Ну метод Dispose() c Finalize() сам по себе не связан никак. Связь определяет реалзиция программистом модели освобождения ресурсов. Я думаю, Вы именно это и имели в виду. Для полноты картины хотелось бы увидеть в листинге хотя бы псевдокод метода DisposeUnmanaged(bool disposing) .

    Ну, это я опечатался. Нету у него никакого параметра.
    A__>ИМХО, GC.SuppressFinalize(this); корректнее всатвить перед вызовами DisposeManaged(); DisposeUnmanaged();.

    A__>Так в чем же все-таки существенное упрощение? Ну вводится локальная переменная вместо bool параметра

    Нет. Локальная переменная уже была. Просто вместо параметра с невнятной семантикой вводится два различных метода с, как мне кажется, более внятной семантикой.
    Единственное различие — в МС-версии сначала освобождаются все ресурсы наследника, затем его предка и т.д. В моей версии сначала освобождаются все управляемые ресурсы, потом все неуправляемые.
    A__>, отдельные виртуальные методы очистки управляемых и неуправляемых ресурсов, которые классы-наследники должны переопределить при необходимости, и все это надо будет держать в голове и реализовывать программисту, так же, как и в случае стандартного паттерна.
    Схема реализации каждого из методов — проще.
    A__>Все-таки то, что приводится в MSDN — паттерн, рекомендованный в общем случае, и, ИМХО, в этой связи сложно придумать что-либо более простое. Конечно же, то, что написано в MSDN, не является приказом, не подлежащим обсуждению, и ничто не мешает реализовать свою модель освобождения ресурсов, как в Вашем случае, и пользоваться ей. Единственное, что способствутет реализации программистом именно интерфейса IDisposable — это языковая поддержка (using, генерирующий блок try... finally с вызовом в последнем Dispose()), ну и само назначение этого интерфейса (реализованного во многих клссах FW) в контексте модели освобождения ресурсов.
    С этим никто не спорит.
    A__>я бы добавил также lock в Dispose, и еще: throw new ObjectDisposedException(); компилироваться не будет
    Это код от МС.
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[4]: Правила использования финалайзеров [blog]
    От: TK Лес кывт.рф
    Дата: 22.01.06 14:35
    Оценка:
    Здравствуйте, Sinclair, Вы писали:

    S>По-моему, так гораздо яснее, и труднее сделать ошибку. Можно еще подумать на тему иерархии классов, где не все обязаны иметь оба типа ресурсов, нуждающихся в финализации.


    Между тем, они уже есть... Например, флаг disposed из BaseResource в MyResourceWrapper уже не доступен. А объявленное поле никак не используется... DisposeUnmanaged(false) в финализаторе тоже никак не понятен.
    Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
    Re[6]: Правила использования финалайзеров [blog]
    От: Alexander__S  
    Дата: 22.01.06 16:07
    Оценка:
    S>Нет. Локальная переменная уже была.

    A__>>я бы добавил также lock в Dispose, и еще: throw new ObjectDisposedException(); компилироваться не будет

    S>Это код от МС.

    Да, действительно. Извиняюсь за то, что не удосужился заглянуть в MSDN. Держал в голове рихтеровскую реализацию. Что ж, можно объявить конкурс на лучшую реализацию паттерна освобождения ресурсов
    Re[5]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 23.01.06 09:01
    Оценка:
    Здравствуйте, TK, Вы писали:

    TK>Здравствуйте, Sinclair, Вы писали:


    S>>По-моему, так гораздо яснее, и труднее сделать ошибку. Можно еще подумать на тему иерархии классов, где не все обязаны иметь оба типа ресурсов, нуждающихся в финализации.


    TK>Между тем, они уже есть... Например, флаг disposed из BaseResource в MyResourceWrapper уже не доступен. А объявленное поле никак не используется... DisposeUnmanaged(false) в финализаторе тоже никак не понятен.

    Виноват, писал с листа. Вот еще один подход:

    public class BaseResource: IDisposable
    {
      private bool _disposed = false;
        public bool Disposed { 
        [DebuggerStepThrough]
        get { return _disposed; }
        
        #region IDisposable implementation
      public void Dispose()
      {
        if (!disposed)
        {
          DisposeManaged();
          DisposeUnmanaged();
          _disposed = true;
          GC.SuppressFinalize(this);
        }
      }
        #endregion
        
      // Dispose managed resources.
      protected virtual void DisposeManaged()
      {
        Components.Dispose();
      }
      // Release unmanaged resources. 
      protected virtual void DisposeUnmanaged()
      {
        CloseHandle(handle);
        handle = IntPtr.Zero;
      }
    
       // Do not provide destructors in types derived from this class.
       ~BaseResource()      
       {
          DisposeUnmanaged();
       }
    
        protected void CheckDisposed()
        {
        if(Disposed)
        {
           throw new ObjectDisposedException();
        }
        }
      public void DoSomething()
      {
          CheckDisposed();
      }
    }
    
    public class MyResourceWrapper: BaseResource
    {
       // A managed resource that you add in this derived class.
       private ManagedResource addedManaged;
       // A native unmanaged resource that you add in this derived class.
       private NativeResource addedNative;
    
      protected override void DisposeManaged()
      {
        addedManaged.Dispose();         
        base.DisposeManaged();
      }
      protected override void DisposeUnmanaged()
      {
        CloseHandle(addedNative);
        base.DisposeUnmanaged();
      }
    }
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[6]: Правила использования финалайзеров [blog]
    От: TK Лес кывт.рф
    Дата: 23.01.06 09:46
    Оценка:
    Hello, "Sinclair"
    >
    > TK>Между тем, они уже есть... Например, флаг disposed из BaseResource в
    > MyResourceWrapper уже не доступен. А объявленное поле никак не
    > используется... DisposeUnmanaged(false) в финализаторе тоже никак не
    > понятен.
    > Виноват, писал с листа. Вот еще один подход:
    >

    Все равно, решение сложное

    Например, нет атомарности освобождения ресурсов. Например, кто-то кидает
    исключение в DisposeManaged. В результате до освобождения unmanaged ресурсов
    дело уже не дойдет. В случае использования стандартного шаблона,
    освобождение своих ресурсов так или иначе гарантировать...
    Posted via RSDN NNTP Server 2.0
    Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
    Re[7]: Правила использования финалайзеров [blog]
    От: Merle Австрия http://rsdn.ru
    Дата: 23.01.06 10:02
    Оценка:
    Здравствуйте, TK, Вы писали:

    TK>Все равно, решение сложное

    Хм... Оно если и не более простое, то все-таки более ООП-истое и более очевидное.

    TK>В случае использования стандартного шаблона,

    TK>освобождение своих ресурсов так или иначе гарантировать...
    ... все равно не получится. В любом случае, если у тебя в Dispose() вылетит exception, то дальше ничего не пройдет.
    И если уж этого опасаться, то в Тохином варианте всегда можно сделать
        if (!disposed)
        {
                try
                {
                    DisposeManaged();
                }
                ...
                finally
                {
                    DisposeUnmanaged();
                }
          _disposed = true;
          GC.SuppressFinalize(this);
        }
    ... << RSDN@Home 1.2.0 alpha rev. 0>>
    Мы уже победили, просто это еще не так заметно...
    Re[8]: Правила использования финалайзеров [blog]
    От: TK Лес кывт.рф
    Дата: 23.01.06 10:45
    Оценка:
    Hello, "Merle"

    > TK>Все равно, решение сложное

    > Хм... Оно если и не более простое, то все-таки более ООП-истое и более
    > очевидное.
    >

    Оно настолько очевидное, что более/менее правильный вариант удалось только с
    третьего раза написать?
    Кстати, если я хочу вызвать GC.ReRegisterForFinalize то, где это лучше
    сделать, в DisposeUnmanaged? тоже, очевидное решение... Так же, действия в
    финализаторе могут быть не обязательно связаны с unmanaged ресурсами...
    Вобщем, название метода DisposeUnmanaged удачным назвать нельзя...

    Да и потом, как узнать в DisposeUnmanaged что именно происходит с объектом —
    был вызван Dispose или запустился финализатор. Флаг завести?
    Posted via RSDN NNTP Server 2.0
    Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
    Re[9]: Правила использования финалайзеров [blog]
    От: mihailik Украина  
    Дата: 23.01.06 11:16
    Оценка:
    TK>Оно настолько очевидное, что более/менее правильный вариант удалось только с
    TK>третьего раза написать?
    TK>Кстати, если я хочу вызвать GC.ReRegisterForFinalize то, где это лучше
    TK>сделать, в DisposeUnmanaged? тоже, очевидное решение... Так же, действия в
    TK>финализаторе могут быть не обязательно связаны с unmanaged ресурсами...
    TK>Вобщем, название метода DisposeUnmanaged удачным назвать нельзя...

    TK>Да и потом, как узнать в DisposeUnmanaged что именно происходит с объектом —

    TK>был вызван Dispose или запустился финализатор. Флаг завести?

    Вот именно эти проблемы-выкрутасы и привели к посту, с которого всё началось.

    ИЗБЕГАЙТЕ ФИНАЛИЗАТОРОВ!
    -заторов.. -аторов...


    Finalize — это не пила, к которой есть стандартная техника безопасности. Скорее это ядерный реактор, который для каждого отдельного случая отдельно настраивается и продумывается.
    Re[9]: Правила использования финалайзеров [blog]
    От: Merle Австрия http://rsdn.ru
    Дата: 23.01.06 11:56
    Оценка:
    Здравствуйте, TK, Вы писали:

    TK>Оно настолько очевидное, что более/менее правильный вариант удалось только с

    TK>третьего раза написать?
    Дело не в очевидности написания, а в очевидности использования.

    TK>Кстати, если я хочу вызвать GC.ReRegisterForFinalize то, где это лучше

    TK>сделать, в DisposeUnmanaged?
    Не, отдельную кнопку приделать.
    ... << RSDN@Home 1.2.0 alpha rev. 0>>
    Мы уже победили, просто это еще не так заметно...
    Re[10]: Правила использования финалайзеров [blog]
    От: TK Лес кывт.рф
    Дата: 23.01.06 11:58
    Оценка:
    Здравствуйте, mihailik, Вы писали:

    M>Вот именно эти проблемы-выкрутасы и привели к посту, с которого всё началось.


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

    M>ИЗБЕГАЙТЕ ФИНАЛИЗАТОРОВ!

    M>-заторов.. -аторов...

    Вот тебя торкает :)

    M>Finalize — это не пила, к которой есть стандартная техника безопасности. Скорее это ядерный реактор, который для каждого отдельного случая отдельно настраивается и продумывается.


    Нужны примеры. Это лучшее средство наглядной агитации.
    Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
    Re[11]: Правила использования финалайзеров [blog]
    От: mihailik Украина  
    Дата: 23.01.06 12:04
    Оценка:
    TK>Нужны примеры. Это лучшее средство наглядной агитации.

    Сложность в том, что примеры или очевидно неправильные, или занимают страницу кода. Кому интересно копаться в килобайтах?

    А правильные примеры настолько простые, что их и приводить не нужно. Класс без финализатора. Простейший класс с простейшим финализатором. Все остальные примеры идут в разряде неправильных.
    Re[10]: Правила использования финалайзеров [blog]
    От: TK Лес кывт.рф
    Дата: 23.01.06 12:14
    Оценка:
    Здравствуйте, Merle, Вы писали:

    TK>>Оно настолько очевидное, что более/менее правильный вариант удалось только с

    TK>>третьего раза написать?
    M>Дело не в очевидности написания, а в очевидности использования.

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

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

    TK>>Кстати, если я хочу вызвать GC.ReRegisterForFinalize то, где это лучше

    TK>>сделать, в DisposeUnmanaged?
    M>Не, отдельную кнопку приделать.

    А в случае с disposing, флажок завести? Не слишком-ли много подпорок для такого "очевидного" решения.
    Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
    Re[11]: Правила использования финалайзеров [blog]
    От: Merle Австрия http://rsdn.ru
    Дата: 23.01.06 12:39
    Оценка:
    Здравствуйте, TK, Вы писали:

    TK>Вот это у вас и хромает.

    разьве?

    TK>В случае же с Dispose(bool disposing) все ясно, понятно,

    Да вот не очень, разица в том, что в классическом варианте ты должен один метод реализовать определенным образом.
    А в предложеном, просто перекрыть то что надо и реализовать как хочется.

    TK>да и все возможные варианты использования покрываются.

    Давай, чтобы быть более конкретным ты просто напишешь возможные варианты использования, а мы попробуем реализовать это так, чтобы использовать было удобнее чем классический вариант.
    ... << RSDN@Home 1.2.0 alpha rev. 0>>
    Мы уже победили, просто это еще не так заметно...
    Re[9]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 24.01.06 03:09
    Оценка:
    Здравствуйте, TK, Вы писали:
    TK>Оно настолько очевидное, что более/менее правильный вариант удалось только с
    TK>третьего раза написать?
    TK>Кстати, если я хочу вызвать GC.ReRegisterForFinalize то, где это лучше
    TK>сделать, в DisposeUnmanaged? тоже, очевидное решение... Так же, действия в
    TK>финализаторе могут быть не обязательно связаны с unmanaged ресурсами...
    Какие, например? С учетом того, что управляемые ресурсы трогать в нем нельзя?
    TK>Вобщем, название метода DisposeUnmanaged удачным назвать нельзя...
    По-моему, так оно как раз очень удачное. Оно отражает функциональность метода.
    TK>Да и потом, как узнать в DisposeUnmanaged что именно происходит с объектом —
    TK>был вызван Dispose или запустился финализатор. Флаг завести?
    А вот это мне больше всего и не нравится в МС-решении. Код должен зависеть не от того, откуда он позвался, а от того, что нужно сделать. Вот объясни мне, какая принципиальная разница для метода DisposeUnmanaged — работает ли он во время финалайзера или нет?
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[13]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 24.01.06 03:09
    Оценка:
    Здравствуйте, TK, Вы писали:

    TK>Уже написал. Флаг disposing. Я хочу знать что происходит с объектом.

    Ты не мог бы привести пример кода, для которого это надо? Пример из MSDN полностью описывается парой методов.
    TK>Кроме того, как то у вас не продумана концепция инициализации объекта. Как
    TK>будут создаваться manged/unmanaged русурсы. Хотелось бы некоторой симетрии в
    TK>действиях. Это тоже будет два разных метода?
    А зачем, пардон, продумывать концепцию инициализации? С инициализацией, слава байту, все и так в порядке. Когда хочешь — тогда и инициализируешь. В симметрии как таковой смысла вообще нету, если она не улучшает понятность кода.
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[14]: Правила использования финалайзеров [blog]
    От: TK Лес кывт.рф
    Дата: 24.01.06 06:40
    Оценка:
    Hello, "Sinclair"
    >
    > TK>Уже написал. Флаг disposing. Я хочу знать что происходит с объектом.
    > Ты не мог бы привести пример кода, для которого это надо? Пример из MSDN полностью описывается парой методов.

    if (!disposing)
    {
        Debug.WriteLine(...);
    }
    Posted via RSDN NNTP Server 2.0
    Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
    Re[16]: Правила использования финалайзеров [blog]
    От: Mika Soukhov Stock#
    Дата: 24.01.06 08:23
    Оценка:
    Здравствуйте, Sinclair, Вы писали:

    S>Вот пацаны из Редмонда предложили некоторую схему. Эта схема лично мне кажется непонятной и неустойчивой к ошибкам. Я не понимаю, зачем было делать метод, параметр которого задает место, откуда его вызвали. Я вообще считаю, что такие вещи крайне противопоказаны в OOD. Потому, что они затрудняют понимание сути метода.


    Можно сделать по-правильному, а можно по-простому. Я привел пример http://gzip.rsdn.ru/Forum/?mid=1607969&amp;flat=0
    Автор: Mika Soukhov
    Дата: 23.01.06
    где твой подход не подойдет. Видимо, разработчики из МС решили сделать универсальное решение.
    Re[10]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 24.01.06 09:51
    Оценка:
    Здравствуйте, Mika Soukhov, Вы писали:
    MS>Мне кажется, что основной проблемой разбиения на два метода будет являтся сценарий, когда неуправляемый ресурс освобождается в зависимости от состояния управляемого ресурса.
    Хм.
    MS>
    MS>public class WindowDescriptor
    MS>{
    MS>  private Form _targetWindow;
    MS>  private int _descId;
    
    MS>  private static extern void CloseDescriptor(IntPtr hwnd, int descId);
    
    MS>  private static extern void CloseAllDescriptors(IntPtr hwnd);
    
    MS>  protected override void DisposeManaged()
    MS>  {
    MS>    _targetWindow.Dispose();
    MS>  }
    
    MS>  protected override void DisposeUnmanaged()
    MS>  {
    MS>    CloseDescriptor(_targetWindow.Handle, _descId); // тут вылезет все, что угодно, т.к. наше окно уже уничтожено.
    MS>  }
    MS>}
    MS>

    Хм. А что будет, если нас позвали не из Dispose(), а из Finalize()? _targetWindow вполне возможно уже был финализирован, т.е. никакого Handle у него уже нет. Надо было сделать так:

    public class WindowDescriptor
    {
      private Form _targetWindow;
      private int _descId;
      private IntPtr _targetHwnd;
        public WindowDescriptor(Form targetWindow)
        {
          _targetWindow = targetWindow;
            _targetHwnd = _targetWindow.Handle;
            _descId = AllocateDescriptor(_targetHwnd);
        }
        private static extern int AllocateDescriptor(IntPtr hwnd);
      private static extern void CloseDescriptor(IntPtr hwnd, int descId);
    
      private static extern void CloseAllDescriptors(IntPtr hwnd);
    
      protected override void DisposeManaged()
      {
        _targetWindow.Dispose();
      }
    
      protected override void DisposeUnmanaged()
      {
        CloseDescriptor(_targetHwnd, _descId); 
      }
    }

    А?
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[11]: Правила использования финалайзеров [blog]
    От: Mika Soukhov Stock#
    Дата: 24.01.06 10:12
    Оценка:
    Здравствуйте, Sinclair, Вы писали:

    S>Хм. А что будет, если нас позвали не из Dispose(), а из Finalize()? _targetWindow вполне возможно уже был финализирован, т.е. никакого Handle у него уже нет. Надо было сделать так:


    Забыл

    S>
    S>public class WindowDescriptor
    S>{
    S>  private Form _targetWindow;
    S>  private int _descId;
    S>  private IntPtr _targetHwnd;
    S>    public WindowDescriptor(Form targetWindow)
    S>    {
    S>      _targetWindow = targetWindow;
    S>        _targetHwnd = _targetWindow.Handle;
    S>        _descId = AllocateDescriptor(_targetHwnd);
    S>    }
    S>    private static extern int AllocateDescriptor(IntPtr hwnd);
    S>  private static extern void CloseDescriptor(IntPtr hwnd, int descId);
    
    S>  private static extern void CloseAllDescriptors(IntPtr hwnd);
    
    S>  protected override void DisposeManaged()
    S>  {
    S>    _targetWindow.Dispose();
    S>  }
    
    S>  protected override void DisposeUnmanaged()
    S>  {
    S>    CloseDescriptor(_targetHwnd, _descId); 
    S>  }
    S>}
    S>

    S>А?

    Не прокатит. Я в своем примере акцент делал не на объект Form, а именно на состояние хендла. Вот смотри. Мы уничтожаем объект окна в DisposeManaged. После этого исполняется метод DisposeUnmanaged. В нем уничтожается дескритор. Именно здесь программа и упадет, так как наше окно давно уже не существует, и HWND передается невалидным. Какой тогда в нем смысл?
    Re[17]: Правила использования финалайзеров [blog]
    От: Mika Soukhov Stock#
    Дата: 24.01.06 10:15
    Оценка:
    Здравствуйте, TK, Вы писали:

    TK>Тут как не крути, но по очкам "альтернативное" решение проигрывает сильнее

    TK>некуда...

    Не, Тим. Я бы такое решение взял бы на заметку. В некоторых случаях его будет достаточно. ИТ тоже свой механизм разработал (довольно удачный), а у него еще ненадежнее.
    Re[12]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 24.01.06 11:18
    Оценка:
    Здравствуйте, Mika Soukhov, Вы писали:
    S>>Хм. А что будет, если нас позвали не из Dispose(), а из Finalize()? _targetWindow вполне возможно уже был финализирован, т.е. никакого Handle у него уже нет. Надо было сделать так:

    MS>Забыл

    MS>Не прокатит. Я в своем примере акцент делал не на объект Form, а именно на состояние хендла. Вот смотри. Мы уничтожаем объект окна в DisposeManaged. После этого исполняется метод DisposeUnmanaged. В нем уничтожается дескритор. Именно здесь программа и упадет, так как наше окно давно уже не существует, и HWND передается невалидным. Какой тогда в нем смысл?
    Я не очень понимаю, как такое может быть. Вот у нас есть неуправляемый ресурс, которым мы владеем. Именно его мы и прибиваем. Как может появиться зависимость от неуправляемого ресурса, которым мы не владеем? Как эту ситуацию разрешить вообще, не в пределах какого-либо паттерна?
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[17]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 24.01.06 11:18
    Оценка:
    Здравствуйте, TK, Вы писали:
    TK>Ущербность твоего решения в том, что на каждый чих приходится править
    TK>реализацию базового класса.
    Пока что такой нужды не возникло. Я просто предположил, что ты хочешь написать в дебаг не для того, чтобы доказать отсутствие аргумента метода, а для какой-то осмысленной цели. Например, для отлова невызванных Dispose(). В таком случае имеет смысл встроить функционал сразу в базовый класс, чтобы облегчить себе задачу.
    TK> Пока я не вижу твоей способности предоставить
    TK>решение свободное от данных недостатков.
    TK>Поэтому, если хочешь отвечать
    TK>конструктивно то для начала хотелось бы видеть возможность, при вызове
    TK>финализатора, добавлять вывод трейса в наследниках BaseResource.
    ~Derived()
    {
      Debug.WriteLine();
    }

    Еще вопросы?
    TK>Кроме того, Mika уже написал свое замечание на тему того, что два раздельных
    TK>метода освобождения ресурса на какой-то момент оставляют объект в
    TK>несогласованном состоянии (ситуацию с финализатором мы пока в расчет не
    TK>берем т.к. это крайний случай и в нормальной ситуации все ресурсы
    TK>освобождаются по Dispose).
    Пока что я не увидел примера корректно работающего кода, который бы не получалось перенести в предлагаемую схему. Я хоть убей не могу придумать, как можно корректно финализировать такой класс. Если не задумываться над ситуацией с финализатором, то все вообще просто, как угол дома: меняем местами вызовы DisposeManaged и DisposeUnmanaged().
    TK>Что касается дизайна в целом то, ситуация пока следующая:
    TK>
  • Dispose Pattern: Один метод с одним аргументом
    И сложной структурой.
    TK>
  • Dispose "Anti" Pattern: Два метода, поле, свойство, нетривиальный код
    TK>(раз уж с первого раза написать не удалось)
    Вот только не надо упирать на ошибки, которые я делаю при наборе вслепую в редакторе без IntelliSense.
    TK>плюс очень похоже, что есть
    TK>проблемы с покрытием существующих use cases (для примера возьмем трейс в
    TK>наследнике)
    Надуманные проблемы.
    1.1.4 stable rev. 510
  • Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[13]: Правила использования финалайзеров [blog]
    От: Mika Soukhov Stock#
    Дата: 24.01.06 12:15
    Оценка:
    Здравствуйте, Sinclair, Вы писали:

    S>Здравствуйте, Mika Soukhov, Вы писали:

    S>>>Хм. А что будет, если нас позвали не из Dispose(), а из Finalize()? _targetWindow вполне возможно уже был финализирован, т.е. никакого Handle у него уже нет. Надо было сделать так:

    MS>>Забыл

    MS>>Не прокатит. Я в своем примере акцент делал не на объект Form, а именно на состояние хендла. Вот смотри. Мы уничтожаем объект окна в DisposeManaged. После этого исполняется метод DisposeUnmanaged. В нем уничтожается дескритор. Именно здесь программа и упадет, так как наше окно давно уже не существует, и HWND передается невалидным. Какой тогда в нем смысл?
    S>Я не очень понимаю, как такое может быть. Вот у нас есть неуправляемый ресурс, которым мы владеем. Именно его мы и прибиваем. Как может появиться зависимость от неуправляемого ресурса, которым мы не владеем?

    Не, не так. Descriptor-ом, по идее, должна владеть сама форма. Тоесть, она должна его создавать, когда инициализируется, и уничтожать, когда закрывается (или в финалайзере, когда уничтожается ее неуправляемые ресурсы).

    S>Как эту ситуацию разрешить вообще, не в пределах какого-либо паттерна?


    protected override Dispose(bool disposing)
    {
      if (_targetHwnd != IntPtr.Zero)
      {
        CloseDescriptor(_targetHwnd, _descId);
        _targetHwnd = IntPtr.Zero;
      }
    
      if (disposing && _targetForm != null)
      {
         _targetForm.Dispose();
         _targetForm = null;
      }
    }


    Тоесть, в моем случае нужно вызвать DisposeUnmanaged перед DisposeManaged. Но это не исключает ситуацию, где нужно сделать наоборот. Отрезюмируя, скажу, что твой подход хороший. Но только там, где не нужен порадок освобождения (как уже ТК написал, атомарность). Иначе придется городить огород.
    Re[14]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 24.01.06 12:48
    Оценка:
    Здравствуйте, Mika Soukhov, Вы писали:
    MS>Не, не так. Descriptor-ом, по идее, должна владеть сама форма. Тоесть, она должна его создавать, когда инициализируется, и уничтожать, когда закрывается (или в финалайзере, когда уничтожается ее неуправляемые ресурсы).
    А какого тогда, извините, хрена, диспоз дескриптора лезет диспозить форму, когда должно быть все наоборот?
    S>>Как эту ситуацию разрешить вообще, не в пределах какого-либо паттерна?

    MS>
    MS>protected override Dispose(bool disposing)
    MS>{
    MS>  if (_targetHwnd != IntPtr.Zero)
    MS>  {
    MS>    CloseDescriptor(_targetHwnd, _descId);
    MS>    _targetHwnd = IntPtr.Zero;
    MS>  }
    
    MS>  if (disposing && _targetForm != null)
    MS>  {
    MS>     _targetForm.Dispose();
    MS>     _targetForm = null;
    MS>  }
    MS>}
    MS>

    Очень хорошо. Мы забыли позвать Dispose, и вызвался финалайзер. Нам также не повезло, и финалайзер формы вызвался первым. Упс, _targetHwnd уже инвалид. Видим crash, вызванный некорректной реализацией финалайзера. Косяк!

    Если это устраивает, то можно просто поменять местами вызовы DisposeManaged и DisposeUnmanaged в базовом Dispose().

    MS>Тоесть, в моем случае нужно вызвать DisposeUnmanaged перед DisposeManaged. Но это не исключает ситуацию, где нужно сделать наоборот.

    Можно ее тоже в студию, эту обратную ситуацию? Как у нас неуправляемый ресурс вдруг собрался зависеть от управляемого?
    MS>Отрезюмируя, скажу, что твой подход хороший. Но только там, где не нужен порадок освобождения (как уже ТК написал, атомарность). Иначе придется городить огород.
    Пока что мы видим косячный код, который косячно работает. Судя по всему, это из-за его неотъемлемой косячности. Надо что-то делать по-другому. Например, форма владеет дескриптором, его DisposeManaged ничего не делает, а CloseDescriptor корректно обрабатывает ситуацию с мертвым Hwnd.


    Более реалистичный случай может быть связан с набором взаимосвязанных дескрипторов неуправляемых ресурсов. Что-то типа RemoteShareConnection, как враппера соединения, и RemoteFile, который требует открытого соединения. Перед закрытием соединения надо закрыть все файлы, иначе попытка не удастся и соединение остается открытым. При этом мы параноидально полагаем, что никакого API по перечислению открытых файлов для соединения неуправляемый мир не предоставляет.

    Я пока не знаю, как корректно реализовывать такую схему в дотнете. В плюсах все было бы нормально, благодаря RAII и детерминистической финализации. А вот как быть в дотнете, если соединение и его файлы выходят из области видимости одновременно, это еще вопрос. Давайте попробуем решить эту задачу вообще как-нибудь, а потом придумаем красивый паттерн, позволяющий повторно использовать полученный результат.
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[18]: Правила использования финалайзеров [blog]
    От: TK Лес кывт.рф
    Дата: 24.01.06 13:04
    Оценка:
    Hello, "Sinclair"

    > Еще вопросы?


    т.е. один if заменили на три метода, поле и свойство? Если ты
    говоришь о паттерне, то его использование должно быть документированным и
    (желательно) очевидным. Поведение Dispose pattern можно описать в пару
    предложений. Можно тоже самое сделать для приведенного тобой примера?

    > Если не задумываться над ситуацией с финализатором, то все вообще просто,

    > как угол дома: меняем местами вызовы DisposeManaged и DisposeUnmanaged().

    т.е. опять меняем базовый класс... и это называется дизайн?

    Кстати, про кривую семантику уже говорили?
    class SomeManagedResource
    {
       byte[] _managedArray;
    
       public SomeResource()
       {
            _managedArray = ManagedAllocate();
       }
    
       protected virtual void Dispose(bool disposing)
       {
            ManagedRelease(_managedArray);
       }
    }


    > Вот только не надо упирать на ошибки, которые я делаю при наборе вслепую в

    > редакторе без IntelliSense.

    IntelliSence спасает от опечаток но, от недостатков в реализации он никак не
    спасет. К опечаткам претензий нет. Я говорил лишь о недостатках в
    реализации.

    > TK>проблемы с покрытием существующих use cases (для примера возьмем трейс

    > в
    > TK>наследнике)
    > Надуманные проблемы.

    Пока я вижу, что все проблемы решаются добавлением "еще одного метода" в
    твой паттерн. Лично мне хотелось бы видеть какое то законченное решение.
    Которое было бы настолько гармоничным, что "ни добавить, ни отнять — все на
    своем месте". Можешь сделать нечто подобное? А то, пока только вопросы да и
    не однозначности возникают (хотя, хотелось бы их разрешить)...
    Posted via RSDN NNTP Server 2.0
    Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
    Re[13]: Правила использования финалайзеров [blog]
    От: Merle Австрия http://rsdn.ru
    Дата: 24.01.06 14:35
    Оценка:
    Здравствуйте, TK, Вы писали:

    TK>Уже написал. Флаг disposing. Я хочу знать что происходит с объектом.

    Да, такой вариант реализовать красиво довольно сложно (если это нужно именно в коде конечного объекта), равно как и разрулить предложенную Микой зависимость между освобождением Managed и Unmanaged ресурсами... Но сдается мне, что это скорее плюс, потому как если возникают подобные зависимости, значит скорее всего объект с ресурсами делает что-то не то. Таким образом Тохин вариант работает как некий тест — если в его реализацию сценарий использования объекта не укладывается, то это повод задуматься...
    Мы уже победили, просто это еще не так заметно...
    Re[17]: Правила использования финалайзеров [blog]
    От: Merle Австрия http://rsdn.ru
    Дата: 24.01.06 15:34
    Оценка:
    Здравствуйте, TK, Вы писали:


    TK>Что касается дизайна в целом то, ситуация пока следующая:

    TK>
  • Dispose Pattern: Один метод с одним аргументом
    TK>
  • Dispose "Anti" Pattern: Два метода, поле, свойство, нетривиальный код
    TK>(раз уж с первого раза написать не удалось) плюс очень похоже, что есть
    TK>проблемы с покрытием существующих use cases (для примера возьмем трейс в
    TK>наследнике)
    Не, Тим, не передергивай...
  • Dispose Pattern (MS): Один метод, с одним аргументом, с неясной семантикой.
  • Dispose Pattern (Sinclair): Два метода, без аргументов, с ясной семантикой, но покрывает не все (при этом вопрос нужно ли все покрывать, оставим пока за скобками).

    Вообще, если уж очень хочется гибкости, то можно сделать так: =)
    public class DisposableObject : IDisposable
    {
        // здесь стандартная реализация.
    }
    
    public class SimpleDisposableObject : DisposableObject
    {
        // здесь реализация с методами.
    }

    Все объекты у которых с ресурсами все очевидно, наследуются от SimpleDisposableObject и просто перекрывают Managed и/или Unmanaged в зависимости от... И таких объектов будет подавляющее большинство.
    Если же нужны какие-то хитрые приседания, то крепко думаем, наследуемся от DisposableObject и реализуем оные приседания.
    При этом, при взгляде на класс, сразу становится понятно, что там с ресурсами происходит, в зависимости от какого объекта он унаследовался. Ну, если вдруг возникнет такая необходимость..
  • Мы уже победили, просто это еще не так заметно...
    Re[18]: Правила использования финалайзеров [blog]
    От: mihailik Украина  
    Дата: 24.01.06 15:40
    Оценка:
    M>Вообще, если уж очень хочется гибкости, то можно сделать так: =)
    M>
    M>public class DisposableObject : IDisposable
    M>{
    M>    // здесь стандартная реализация.
    M>}
    
    M>public class SimpleDisposableObject : DisposableObject
    M>{
    M>    // здесь реализация с методами.
    M>}
    M>


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

    Есть враппер над неуправляемым объектом — у него простое очевидное время жизни. Есть управляемые объекты — у них ещё проще: никакой финализации, только Dispose. Параметры тут вообще не нужны, так как из финализатора вызовов не бывает.

    Вот отдельная тема:
    <b>Финализаторы 2</b>
    Автор: mihailik
    Дата: 24.01.06
    Re[18]: Правила использования финалайзеров [blog]
    От: TK Лес кывт.рф
    Дата: 24.01.06 16:01
    Оценка:
    Hello, "Merle"
    > Не, Тим, не передергивай...

    А в чем передергиание, можно по пунктам?

    >
  • Dispose Pattern (MS): Один метод, с одним аргументом, с неясной
    > семантикой.

    А можно по подробнее... Что именно не понятно в этом методе? Может, я тоже
    что-то упустил?

    >
  • Dispose Pattern (Sinclair): Два метода, без аргументов, с ясной
    > семантикой, но покрывает не все (при этом вопрос нужно ли все покрывать,
    > оставим пока за скобками).
    >

    Очевидность вашего решения явно не блещет. То, вначале вызывается
    DisposeManaged, то DisposeUnmanaged. Совершенно не понятно... Лично у меня
    сложилась твердая уверенность, что данный паттерн не результат какого-то
    опыта, а просто первое, что пришло в голову и на это что-то находу
    навешивается какая-то функциональность... "так не работает... ну ладно... а
    если так?". кубик рубика прям какой то...

    Пример про семантику уже приводил. У нас есть достаточно ценный managed
    ресурс который стоит вернуть владельцу. Почему, метод для его возвращения
    должен называться DisposeUnmanaged? На мой взгляд, проблемы в понимании
    оригинального Dispose pattern переносятся на последующие решения.

    > Все объекты у которых с ресурсами все очевидно, наследуются от

    > SimpleDisposableObject и просто перекрывают Managed и/или Unmanaged в
    > зависимости от... И таких объектов будет подавляющее большинство.
    > Если же нужны какие-то хитрые приседания, то крепко думаем, наследуемся от
    > DisposableObject и реализуем оные приседания.

    А не получится так, что крепко думаем, плюемся на автора DisposableObject и
    переписываем все по нормальному? Хотя если закладываться на необходимость
    дальнейшего support-а это может быть более перспективным... Опять таки,
    рефакторинг можно сразу запланировать

    > При этом, при взгляде на класс, сразу становится понятно, что там с

    > ресурсами происходит, в зависимости от какого объекта он унаследовался.
    > Ну, если вдруг возникнет такая необходимость..

    Совершенно не понятно. Хотя, переименуйте ваш DisposableObject в
    UnmanagedResourceWrapperWithLimitedDispose и никаких претензий не будет
    Posted via RSDN NNTP Server 2.0
  • Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
    Re[19]: Правила использования финалайзеров [blog]
    От: Merle Австрия http://rsdn.ru
    Дата: 24.01.06 17:14
    Оценка:
    Здравствуйте, TK, Вы писали:

    TK>А в чем передергиание, можно по пунктам?

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

    TK>А можно по подробнее... Что именно не понятно в этом методе? Может, я тоже

    TK>что-то упустил?
    Опять, тебе уже Тоха три раза написал, что ему (да и мне), не нравится тот факт, что на один маленький метод возложена куча разного ыункционала и реализовывать его нужно в этом методе, строго определенным образом в зависимости от ситуации.
    В идеале, хотелось бы, всю логику вынести в базовый класс, а конечным объектам оставить только возможность просто перекрыть, нужные методы, в которых сама логика освобождения не трогается.

    TK>То, вначале вызывается DisposeManaged, то DisposeUnmanaged.

    Совершенно не важно что вызывается в начале

    TK> "так не работает... ну ладно... а если так?". кубик рубика прям какой то...

    Не кубик-рубик, а обкатка идеи. Собственно для этого форум и существует...

    TK> Почему, метод для его возвращения должен называться DisposeUnmanaged?

    А кто сказал, что он должен так называться?

    TK>На мой взгляд, проблемы в понимании оригинального Dispose pattern переносятся на последующие решения.

    Ну так объясни, если мы, по твоему, не понимаем...

    TK>А не получится так, что крепко думаем, плюемся на автора DisposableObject и

    TK>переписываем все по нормальному?
    DisposableObject — это и есть классическая реализация Disposable Pattern.
    Мы уже победили, просто это еще не так заметно...
    Re[20]: Правила использования финалайзеров [blog]
    От: TK Лес кывт.рф
    Дата: 24.01.06 20:14
    Оценка:
    Hello, "Merle"
    >
    > TK>А не получится так, что крепко думаем, плюемся на автора DisposableObject и
    > TK>переписываем все по нормальному?
    > DisposableObject — это и есть классическая реализация Disposable Pattern.

    Вообще, классическая реализация (приводится в MSDN да и практически в любой книжке) это:

    public class DisposableObject : IDisposable
    {
        public void Dispose()
        {
            Dispose(true);
        }
        
        protected virtual void Dispose(bool disposing)
        {
        }
    
        ~Dispose()
        {
            Dispose(false);
        }
    }


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

    Что касается передергивания, обычно под этим понимается некоторая подмена начальных фактов:

    TK>> Почему, метод для его возвращения должен называться DisposeUnmanaged?
    M>А кто сказал, что он должен так называться?

    Иван, это был твой с синклером код. Это не я придумал назвать метод DisposeUnmanaged. В любом случае, отвечать вопросом на вопрос мягко говоря некрасиво. Пожалуйста, ответь нормально (например, можно привести пример реализации на базе вашего паттерна. тебя ведь не затруднит? ).

    TK>>То, вначале вызывается DisposeManaged, то DisposeUnmanaged.
    M>Совершенно не важно что вызывается в начале

    Если это не важно, то почему тогда нельзя быть последовательными? Разве, это я привел данный
    Автор: Merle
    Дата: 23.01.06
    код? Если ты утверждаешь, что порядок освобождения ресурсов не важен то, можно это как-то логически обосновать? Лично мне кажется, что это утверждение как минимум спорно...

    Ну и кроме всего, раз мы "обкатываем" идею. Можешь написать обновленный код реализации (желательно отдельным сообщением) а то, я уже теряюсь относительно того что-же мы обсуждаем. Или, о коде речь больше не идет, и топик пора махнуть в философию?

    PS
    Я вас там не сильно придавил ?
    Posted via RSDN NNTP Server 2.0
    Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
    Re[21]: Правила использования финалайзеров [blog]
    От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
    Дата: 24.01.06 20:18
    Оценка:
    Здравствуйте, TK, Вы писали:

    Зато какой слог. Получил чисто эстетическое наслаждение.
    и солнце б утром не вставало, когда бы не было меня
    Re[20]: Правила использования финалайзеров [blog]
    От: TK Лес кывт.рф
    Дата: 24.01.06 21:26
    Оценка:
    Здравствуйте, Merle, Вы писали:

    TK>>А не получится так, что крепко думаем, плюемся на автора DisposableObject и

    TK>>переписываем все по нормальному?
    M>DisposableObject — это и есть классическая реализация Disposable Pattern.

    Да, про DisposableObject это лишнее. Подпорки под оригинальный BaseResource возводятся с такой скоростью, что уследить за деталями становится очень сложно Очень тебя прошу, когда начинаешь отвечаеть, следуй уже выбранной системе именований (фильтры очень сложно настраивать... то у вас класс BaseResource называется то, SimpleDisposableObject. Никакой последовательности).

    Поэтому, тему с DisposableObject будем считать, что досрочно слили =)

    Итого, остаются непроясненными следующие вопросы:

    Что касается передергивания, обычно под этим понимается некоторая подмена начальных фактов:

    TK>> Почему, метод для его возвращения должен называться DisposeUnmanaged?
    M>А кто сказал, что он должен так называться?

    Иван, это был твой с синклером код. Это не я придумал назвать метод DisposeUnmanaged. В любом случае, отвечать вопросом на вопрос мягко говоря некрасиво. Пожалуйста, ответь нормально (например, можно привести пример реализации на базе вашего паттерна. тебя ведь не затруднит? ).

    TK>>То, вначале вызывается DisposeManaged, то DisposeUnmanaged.
    M>Совершенно не важно что вызывается в начале

    Если это не важно, то почему тогда нельзя быть последовательными? Разве, это я привел данный
    Автор: Merle
    Дата: 23.01.06
    код? Если ты утверждаешь, что порядок освобождения ресурсов не важен то, можно это как-то логически обосновать? Лично мне кажется, что это утверждение как минимум спорно...

    Ну и кроме всего, раз мы "обкатываем" идею. Можешь написать обновленный код реализации (желательно отдельным сообщением) а то, я уже теряюсь относительно того что-же мы обсуждаем. Или, о коде речь больше не идет, и топик пора махнуть в философию?

    PS
    Я вас там не сильно давлю ?
    Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
    Re[19]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 25.01.06 04:05
    Оценка:
    Здравствуйте, TK, Вы писали:
    TK>Очевидность вашего решения явно не блещет. То, вначале вызывается
    TK>DisposeManaged, то DisposeUnmanaged. Совершенно не понятно... Лично у меня
    TK>сложилась твердая уверенность, что данный паттерн не результат какого-то
    TK>опыта, а просто первое, что пришло в голову и на это что-то находу
    TK>навешивается какая-то функциональность... "так не работает... ну ладно... а
    TK>если так?". кубик рубика прям какой то...
    Совершенно верно. Я просто не могу понять смысла предлагаемого МС паттерна.
    Может, это я тупой? Ты тут утверждал, что можно описать его парой предложений. Опиши, если тебе нетрудно. Что, к примеру, означает параметр disposing?
    Почему в примере МС в классе-наследнике два поля disposed?

    TK>Пример про семантику уже приводил. У нас есть достаточно ценный managed

    TK>ресурс который стоит вернуть владельцу. Почему, метод для его возвращения
    TK>должен называться DisposeUnmanaged?
    Не должен. Метод для возврата управляемых ресурсов называется DisposeManaged.
    TK>На мой взгляд, проблемы в понимании
    TK>оригинального Dispose pattern переносятся на последующие решения.
    Ок, тогда объясни.

    TK>А не получится так, что крепко думаем, плюемся на автора DisposableObject и

    TK>переписываем все по нормальному?
    А что именно по-нормальному? Пока что критика совершенно невнятная. Еще раз пишу русским по белому:
    я взял ровно пример микрософта и переписал его таким образом, чтобы вместо одного сложного метода в наследнике надо было перекрывать два простых.
    Ты занимаешься графоманией и абстрактным плеванием в низкое качество кода. Я привел идею, а не опубликованную библиотеку.
    Мика хотя бы привел пример кода, хотя и некорректный. Я ответил на его примеры. Хотя твоя позиция "ситуацию с финализатором мы пока в расчет не
    берем т.к. это крайний случай и в нормальной ситуации все ресурсы освобождаются по Dispose" ясно показывает твое нежелание вообще разбираться в сути вопроса. Если финалайзер в расчет не брать, то вообще париться не надо — не пиши финалайзер да и все. Реализация Dispose() становится тривиальной. В том то и проблема, что надо брать финалайзер в расчет.

    Так что пока что я вижу только "я в трех книжках прочел, значит — так правильно".

    TK>Совершенно не понятно. Хотя, переименуйте ваш DisposableObject в

    TK>UnmanagedResourceWrapperWithLimitedDispose и никаких претензий не будет
    Я думаю будут. Вот конструктива, похоже, точно ожидать не приходится.
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[20]: Правила использования финалайзеров [blog]
    От: TK Лес кывт.рф
    Дата: 25.01.06 05:33
    Оценка:
    Hello, "Sinclair"

    > Совершенно верно. Я просто не могу понять смысла предлагаемого МС паттерна.

    > Может, это я тупой? Ты тут утверждал, что можно описать его парой предложений. Опиши, если тебе нетрудно. Что, к примеру, означает параметр disposing?

    Если параметр diposing true то это значит то, что необходимо освободить все используемые ресурсы. В случае если параметр disposing false это значит то, ресурсы которые умеют освобождаться сами уже освободились и освобождать надо только тех которые сами этого делать не умеют.

    > Почему в примере МС в классе-наследнике два поля disposed?


    Лучше привести пример. Или ссылку на него. Я в этой ветке пример приводил. Можно посмотреть на него или на System.ComponentModel.Componet никаких полей там нет.

    > TK>Пример про семантику уже приводил. У нас есть достаточно ценный managed

    > TK>ресурс который стоит вернуть владельцу. Почему, метод для его возвращения
    > TK>должен называться DisposeUnmanaged?
    > Не должен. Метод для возврата управляемых ресурсов называется DisposeManaged.

    В вашем оригинальном решении DisposeManaged при финализации не вызывается. т.е. ради идеологической чистоты предлагается не возвращать ресурс в пул? Я правильно понимаю?

    > я взял ровно пример микрософта и переписал его таким образом, чтобы вместо одного сложного метода в наследнике надо было перекрывать два простых — какой вызывается первым, какой вторым. это должно быть зафиксировано, а не так что, "посмотрим по поведению". Особенно, если предлагается сделать некоторый базовый класс.


    Покажи, какой пример ты переписал. Я уже просил описать поведение этих методов. Кроме того, можно привести некоторую "reference" реализацию данного паттерна и пару примеров на ее основе?

    > Так что пока что я вижу только "я в трех книжках прочел, значит — так правильно".


    Это зря. Слепо верить книжкам не надо. Лучше лишний раз подумать

    > TK>Совершенно не понятно. Хотя, переименуйте ваш DisposableObject в

    > TK>UnmanagedResourceWrapperWithLimitedDispose и никаких претензий не будет
    > Я думаю будут. Вот конструктива, похоже, точно ожидать не приходится.

    Наверное, ты просто не хочешь видеть конструктива. Я тебе привел несколько use case-ов:
    1. Надежный возврат managed ресурса в пул
    2. Трейс факта "потери ресурса" (для простоты напишу, что мне необходимо освободить ресурсы объекта и записать об этом факте в лог)

    Можешь написать показать как ваш паттерн решает эту задачу?

    PS
    Антон, можно вас попросить в ответах делать больший акцент на теме обсуждения, а не на моих недостатках? А в качестве доброй воли конструктивизма очень бы хотелось получить ответ на это
    Автор: TK
    Дата: 24.01.06
    сообщение. там было пару вопросов и "неконструктивный" пример кода. Можно на это ответить? (для кода хотелось посмотреть как это будет сделано с "новым" паттерном)
    Posted via RSDN NNTP Server 2.0
    Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
    Re[19]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 25.01.06 07:08
    Оценка:
    Здравствуйте, TK, Вы писали:

    TK>т.е. один if заменили на три метода, поле и свойство?

    Поле уже было. Свойство пришлось ввести для того, чтобы наследники получили к нему доступ. В оригинальном примере его не было, зато был бред в виде дополнительного поля. Что открывает замечательный простор по его сбросу обратно в false, рассогласованию состояний этих полей и прочему сабантую.
    TK>Если ты говоришь о паттерне, то его использование должно быть документированным и
    TK>(желательно) очевидным. Поведение Dispose pattern можно описать в пару
    TK>предложений.
    Опиши. Можно даже в тройку предложений. А то может я просто чего-то очевидного непонимаю?
    TK>Можно тоже самое сделать для приведенного тобой примера?
    Да.

    Перегрузите метод DisposeManaged() в том случае, если ваш объект владеет другими объектами, реализующими IDisposable, и вызовите их Dispose().
    Перегрузите метод DisposeUnmanaged() в том случае, если ваш объект владеет какими-либо неуправляемыми ресурсами.

    Всё. Конец цытаты.
    >> Если не задумываться над ситуацией с финализатором, то все вообще просто,
    >> как угол дома: меняем местами вызовы DisposeManaged и DisposeUnmanaged().

    TK>т.е. опять меняем базовый класс... и это называется дизайн?

    Это называется поиск дизайна.
    TK>Кстати, про кривую семантику уже говорили?
    TK>
    TK>class SomeManagedResource
    TK>{
    TK>   byte[] _managedArray;
    
    TK>   public SomeResource()
    TK>   {
    TK>        _managedArray = ManagedAllocate();
    TK>   }
    
    TK>   protected virtual void Dispose(bool disposing)
    TK>   {
    TK>        ManagedRelease(_managedArray);
    TK>   }
    TK>}
    TK>

    Что это такое? Что означает ManagedAllocate(), что делает ManagedRelease()? Этот пример кода вообще не будет работать, т.к. некому вызвать Dispose. Если имелось в виду наследование этого класса от МС-примера, то объясни мне
    а) почему _managedArray не будет собран сборщиком мусора сам по себе, без наших усилий помешать ему делать его работу?
    б) что гарантирует нам корректную работу ManagedRelease() при вызове из финалайзера, когда нельзя полагаться на нефинализированность других объектов?

    TK>IntelliSence спасает от опечаток но, от недостатков в реализации он никак не

    TK>спасет. К опечаткам претензий нет. Я говорил лишь о недостатках в
    TK>реализации.

    >> TK>проблемы с покрытием существующих use cases (для примера возьмем трейс

    >> в
    >> TK>наследнике)
    >> Надуманные проблемы.

    TK>Пока я вижу, что все проблемы решаются добавлением "еще одного метода" в

    TK>твой паттерн. Лично мне хотелось бы видеть какое то законченное решение.
    Мне бы тоже. Но у меня его нет. Есть решение от МС, которое я не понимаю. Я не пытаюсь научить тебя правильно программировать под дотнет. Я пытаюсь понять, зачем МС сделала такую странную реализацию, и можно ли сделать лучше.
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[21]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 25.01.06 07:08
    Оценка:
    Здравствуйте, TK, Вы писали:
    TK>Если параметр diposing true то это значит то, что необходимо освободить все используемые ресурсы. В случае если параметр disposing false это значит то, ресурсы которые умеют освобождаться сами уже освободились и освобождать надо только тех которые сами этого делать не умеют.
    Что значит "сами не умеют"? Как отличить ресурс, который "умеет освобождаться сам"?
    TK>Лучше привести пример. Или ссылку на него. Я в этой ветке пример приводил. Можно посмотреть на него или на System.ComponentModel.Componet никаких полей там нет.
    Вот пример. Посмотри сам. В MyResourceWrapper: BaseResource два поля disposed.
    http://msdn2.microsoft.com/en-us/library/fs2xkftw.aspx#Mtps_DropDownFilterText

    TK>В вашем оригинальном решении DisposeManaged при финализации не вызывается. т.е. ради идеологической чистоты предлагается не возвращать ресурс в пул? Я правильно понимаю?

    Совершенно верно. Не вызывается. Потому, что управляемые ресурсы, ссылки на которые ведут из нашего объекта, могли уже быть финализированы.
    >> Так что пока что я вижу только "я в трех книжках прочел, значит — так правильно".
    TK>Это зря. Слепо верить книжкам не надо. Лучше лишний раз подумать
    Вот я и пытаюсь думать. А ты меня непрерывно критикуешь. Я не хейльсберг, я только учусь.
    TK>Наверное, ты просто не хочешь видеть конструктива. Я тебе привел несколько use case-ов:
    TK>1. Надежный возврат managed ресурса в пул
    Над этим я подумаю.
    TK>2. Трейс факта "потери ресурса" (для простоты напишу, что мне необходимо освободить ресурсы объекта и записать об этом факте в лог)
    TK>Можешь написать показать как ваш паттерн решает эту задачу?
    Я тебе уже написал, как оттрейсить потерю ресурса. Снова написать?

    TK>PS

    TK>Антон, можно вас попросить в ответах делать больший акцент на теме обсуждения, а не на моих недостатках? А в качестве доброй воли конструктивизма очень бы хотелось получить ответ на это
    Автор: TK
    Дата: 24.01.06
    сообщение. там было пару вопросов и "неконструктивный" пример кода. Можно на это ответить? (для кода хотелось посмотреть как это будет сделано с "новым" паттерном)
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[4]: Правила использования финалайзеров [blog]
    От: mihailik Украина  
    Дата: 25.01.06 08:02
    Оценка:
    M>>— быстро и внятно объяснить, что ему редко есть применение в собственных классах;
    M>>— и тут же уводить разговор к Dispose.

    RU>Тем самым можно усугубить проблему. Запретный плод сладок — будут финалайзить тайно, когда никто не видит... Хотя сублимировать в сторону IDisposable сии постыдные желания пофинализировать — есть намерение безусловно благое.


    Во-во. Сейчас приходится бегать, агитировать, делать плод ЗАПРЕТНЫМ. Люди шарахаются, сомневается, получается давка.

    А если бы сразу написали в нужном ключе, методологически правильно — не было бы повода для подростковых комплексов.
    Re[22]: Правила использования финалайзеров [blog]
    От: TK Лес кывт.рф
    Дата: 25.01.06 08:40
    Оценка:
    Hello, "Sinclair"
    > TK>Если параметр diposing true то это значит то, что необходимо освободить
    > все используемые ресурсы. В случае если параметр disposing false это
    > значит то, ресурсы которые умеют освобождаться сами уже освободились и
    > освобождать надо только тех которые сами этого делать не умеют.
    > Что значит "сами не умеют"? Как отличить ресурс, который "умеет
    > освобождаться сам"?

    Надо думать и читать документацию по используемым классам

    > TK>Лучше привести пример. Или ссылку на него. Я в этой ветке пример

    > приводил. Можно посмотреть на него или на System.ComponentModel.Componet
    > никаких полей там нет.
    > Вот пример. Посмотри сам. В MyResourceWrapper: BaseResource два поля
    > disposed.
    > http://msdn2.microsoft.com/en-us/library/fs2xkftw.aspx#Mtps_DropDownFilterText

    А... это. Про это уже высказался выше. завязывай с этими книжками. они тебя
    плохому учат

    > Совершенно верно. Не вызывается. Потому, что управляемые ресурсы, ссылки

    > на которые ведут из нашего объекта, могли уже быть финализированы.

    Финализируются объекты (и то не все, а только те у которых определен
    финалайзер), а не ссылки.

    Вобщем, думаю, что пора завязывать.
    Posted via RSDN NNTP Server 2.0
    Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
    Re[21]: Правила использования финалайзеров [blog]
    От: Merle Австрия http://rsdn.ru
    Дата: 25.01.06 09:38
    Оценка:
    Здравствуйте, TK, Вы писали:

    TK>Ваше с синклером изделие как его не тяни но, на "классику" уж точно не тянет...

    Да мы и не претендуем.

    TK> А то, фильтровать очень сложно получается...

    Что сложно отфильтровать? классический паттерн — это классический паттерн. Что непонятного?

    TK>Что касается передергивания, обычно под этим понимается некоторая подмена начальных фактов:

    Равно как и старательно игнорирование сути и придирки к несущественным аспектам, хочешь поговорить об этом?

    TK>Иван, это был твой с синклером код.

    Был.

    TK> Это не я придумал назвать метод DisposeUnmanaged.

    Не ты, но ты решил, что он будет освобождать управляемые ресурсы.

    TK> В любом случае, отвечать вопросом на вопрос мягко говоря некрасиво.

    Хочешь поговорить об этом?

    TK> Пожалуйста, ответь нормально

    Да я ответил нормально, причем предложил целых два варианта.

    TK>Ну и кроме всего, раз мы "обкатываем" идею. Можешь написать обновленный код реализации

    Боюсь, что нет, сейчас, к сожалению, совсем нет времени. А основная идея вообщем проста:
    Один метод с определенной реализацией vs десять методов с произвольной реализацией. При том, что в 9 случаях из 10 достаточно будет перекрыть DisposeManaged().

    TK>Я вас там не сильно придавил ?

    Как маленький слоненок, уже проще забить, чем пытаться что-то объяснить..
    Мы уже победили, просто это еще не так заметно...
    Re[22]: Правила использования финалайзеров [blog]
    От: TK Лес кывт.рф
    Дата: 25.01.06 09:56
    Оценка:
    Hello, "Merle"

    > Хочешь поговорить об этом?


    Не, хватит. Синклер уже обрисовал ситуацию
    Posted via RSDN NNTP Server 2.0
    Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
    Re[23]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 25.01.06 10:05
    Оценка:
    Здравствуйте, TK, Вы писали:

    TK>Надо думать и читать документацию по используемым классам

    А, ну это совет сродни "пишите аккуратно, не делая ошибок". Может, хоть какой-то критерий подскажешь? Что искать в документации? Наличие финалайзера? Реализацию IDisposable()?
    Ты же утверждал, что можно двумя предложениями все это объяснить.
    TK>А... это. Про это уже высказался выше. завязывай с этими книжками. они тебя
    TK>плохому учат
    Ок, тогда с чем развязывать? Где тот паттерн, на который ссылаешься ты? Я вижу только какую-то убогость. Тебе она тоже не нравится. Наверное, есть какой-то более другой паттерн, который правильнее обоих вариантов — моего и редмондского?
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[24]: Правила использования финалайзеров [blog]
    От: Mika Soukhov Stock#
    Дата: 25.01.06 10:14
    Оценка:
    Здравствуйте, Sinclair, Вы писали:

    TK>>А... это. Про это уже высказался выше. завязывай с этими книжками. они тебя

    TK>>плохому учат
    S>Ок, тогда с чем развязывать? Где тот паттерн, на который ссылаешься ты? Я вижу только какую-то убогость. Тебе она тоже не нравится. Наверное, есть какой-то более другой паттерн, который правильнее обоих вариантов — моего и редмондского?

    Не могу сказать насчет правильности, но я стараюсь использовать SafeHandle.
    Re[21]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 25.01.06 11:47
    Оценка:
    Здравствуйте, TK, Вы писали:

    TK>Тут сразу вопрос. А это поле вообще в базовой реализации нужно?

    См. базовую реализацию. Вкратце:
    1. Нужно корректно обрабатывать повторный вызов Dispose().
    2. Нужно кидать исключение ObjectDisposedException во всех остальных методах после Dispose.

    TK>т.е. порядок вызова DisposeUnmanaged / DisposeManaged не специфицирован?

    TK>рассмотрим ситуацию. есть объект под названием Dialogue который
    TK>инкапсулирует в себе некий диалог работы с каналом (unmanaged ресурс). При
    TK>вызове Dispose нам надо корректно завершить диалог (сказать что я
    TK>пользователь (информация о пользователе это managed ресурс) такой-то работу
    TK>завершаю). Соответственно вопрос: как надежно завершить работу в ситуации
    TK>когда порядок вызовов DisposeManaged / DisposeUnmanaged не специфицирован? В
    TK>DisposeUnmanaged этого по идее сделать нельзя т.к. managed ресурсы уже могут
    TK>быть недоступны. Как это сделать из DisposeManaged тоже не ясно т.к.
    TK>реализация может вызвать DisposeUnmanaged раньше. Можешь как-то прояснить
    TK>данный аспект в своем описании?
    Могу. Надо заранее скопировать информацию о пользователе в ресурс, который не будет отпущен в DisposeManaged(). Я приводил пример для хэндла окна в ответе на вопрос Мики.


    TK>Ну ок. Уже второй день пошел как мы это обсуждаем. Можно зафиксировать

    TK>какое-то решение?
    Пока нет.

    TK>a. Ключевое слово это ПУЛ ОБЪЕКТОВ. Есть объекты безконтрольное

    TK>создание/уничтожение которых является достаточно накладной операцией.
    TK>Поэтому, в некоторых случаях, имеет смысл организовать пул подобных
    TK>объектов. При этом, для реализации такого пула задействовать какие либо
    TK>unmanaged ресурсы вовсе не обязательно.
    TK>б. Если ты не понял код, то давай его перепишем более понятно:
    Давай.
    Вот пример использования:
    public static void Main()
    {
      using (SomeManagedResource resource1 = new SomeManagedResource())
        {
          resource1 = new SomeManagedResource();
        }
    }

    Внимание, вопрос: сколько памяти осталось занято при выходе из Main()?
    Ладно, это была шутка в сторону. Понятно, что вместо единственного статического поля будет некий список "занятых" и "свободных", и нужно вовремя перекладывать из одного списка в другой. Ок, я понял, в чем проблема. Получается, что у нас есть объекты, которые перекрывают Finalize (и их в финалайзере трогать нельзя и не надо), и объекты, которые его не перекрывают. Значит, нужно провести разделение не по Managed/Unmanaged, а по Finalizable/NonFinalizable:

    public class BaseResource : IDisposable
    {
      private bool _disposed = false;
        protected bool IsDisposed { return _disposed;}
        
        public void Dispose()
        {
          if (_disposed)
                return;
          DisposeFinalizable();
            DisposeNonFinalizable();
            GC.SuppressFinalize(this);
            _disposed = true;
        }
        
        ~BaseResource()
        {
          DisposeNonFinalizable();
        }
        
        protected void DisposeFinalizable() {}
        protected void DisposeNonFinalizable() {}
    }


    Вот мы наследуемся для реализации твоего примера:

    class SomeManagedResource : BaseResource
    {
      byte[] _managedResource;
      static byte[] _cache;
    
      public SomeManagedResource()
      {
        _managedResource = ManagedAllocate();
      }
    
      override protected void DisposeNonFinalizable()
        {
        ManagedRelease(_managedResource);
            base.DisposeNonFinalizable();
      }
      
        ~SomeManagedResource()
        {
          Debug.Trace("Warning! Instance of SomeManagedResource has not been properly disposed. This leads to an ineffective pool usage!");
        }
      static byte[] ManagedAllocate()
      {
        byte[] resource;
        if (_cache == null)
        {
          resource = new byte[VERY_BIG_ARRAY];
        }
        else
        {
          resource = _cache;
          _cache = null;
        }
    
        return resource;
      }
    
      static void ManagedRelease(byte[] resource)
      {
        _cache = resource;
      }
    }

    Что еще я упустил?
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[4]: Правила использования финалайзеров [blog]
    От: vdimas Россия  
    Дата: 27.01.06 12:00
    Оценка:
    Здравствуйте, Sinclair, Вы писали:

    S>Вообще, я до сих пор не могу понять этих приплясываний с bool параметром.

    S>почему нельзя сделать вот так:

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

    Булевская локальная переменная — вполне себе выдержана в духе обычного локального контекста для конкурирующих потоков.

    На самом деле можно вводить disposed для unmanaged-ресурсов как дополнение к булевскому флагу + блокировки, если это критично для используемых unmanaged ресурсов, ибо никто не застрахован от многократных конкурирующих Dispose.
    Re[5]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 27.01.06 12:35
    Оценка:
    Здравствуйте, vdimas, Вы писали:
    V>Потому как доступ к полу disposed в этом случае следовало бы сделать блокируемым. Я понимаю, что вряд ли у кого-то получится явно задиспозить из другого потока в момент финализации, но мало-ли что...
    В момент финализации задиспозить ни из какого потока не "вряд ли", а невозможно. Потому что в очередь финализации попадают только те объекты, на которые уже нет ссылок.
    V>Булевская локальная переменная — вполне себе выдержана в духе обычного локального контекста для конкурирующих потоков.
    Ты, похоже, смешал в кучу параметр disposing и поле disposed, которые имеют совершенно различный смысл и используются независимо. Перечитай еще раз пример.
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[18]: Правила использования финалайзеров [blog]
    От: Hacker_Delphi Россия  
    Дата: 29.01.06 14:03
    Оценка:
    Здравствуйте, Sinclair, Вы писали:

    S>Пока что такой нужды не возникло. Я просто предположил, что ты хочешь написать в дебаг не для того, чтобы доказать отсутствие аргумента метода, а для какой-то осмысленной цели. Например, для отлова невызванных Dispose(). В таком случае имеет смысл встроить функционал сразу в базовый класс, чтобы облегчить себе задачу.

    Кстати о финализаторах...
    Я вот знаю как минимум еще одно место, где они нужны, но при этом нет никакого IDisposable, ибо нету никаких Unmanaged ресурсов
    Например, есть у нас Cache, в котором висят WeakReference'ы объектов.
    При финализации надо бы эти референсы из Cache вычистить...
    Единственный способ — запихать код удаления в финализатор.
    Способ с проверкой WeakReference.IsAlive тоже используется — как ни странно, периодически попадаются моменты, когда WeakReference уже "мертв", а финализатор еще не был вызван...
    Вот в таком случае нужен финализатор и никуда не сдался IDisposable.
    А насчет MS паттерна Disposable(bool), используемого в System.Windows.Forms — он вполне удобен...
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
    Re[19]: Правила использования финалайзеров [blog]
    От: Hacker_Delphi Россия  
    Дата: 29.01.06 14:12
    Оценка:
    Здравствуйте, mihailik, Вы писали:

    M>Есть враппер над неуправляемым объектом — у него простое очевидное время жизни. Есть управляемые объекты — у них ещё проще: никакой финализации, только Dispose. Параметры тут вообще не нужны, так как из финализатора вызовов не бывает.

    Ну не совсем так... см. Re[18]: Правила использования финалайзеров
    Автор: Hacker_Delphi
    Дата: 29.01.06
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
    Re[19]: Правила использования финалайзеров [blog]
    От: mihailik Украина  
    Дата: 29.01.06 20:01
    Оценка:
    H_D>Кстати о финализаторах...
    H_D>Я вот знаю как минимум еще одно место, где они нужны, но при этом нет никакого IDisposable, ибо нету никаких Unmanaged ресурсов
    H_D>Например, есть у нас Cache, в котором висят WeakReference'ы объектов.

    Тут ты ошибся. Даже не в деталях, а в корне ошибся.

    Если твой объект "держит" ссылки на другие управляемые объекты, то финализатор вообще не поможет. Когда твой объект будет мусором, то он уже не будет "держать" никого. Есть ли из него ссылки, нет ли — уже никого не волнует. Мёртвые не потеют.

    Если же говорить о частностях, то WeakReference не считаются ссылками и не мешают объектам становится мусором.
    Re[7]: Правила использования финалайзеров [blog]
    От: Alexander__S  
    Дата: 29.01.06 20:29
    Оценка:
    Здравствуйте, eisernWolf, Вы писали:

    Офигеть... Только сейчас заметил.

    W>[

    W>Переписка из блога.

    W>mihailik >>>>Многие наши программисты предпочитают что-то слащаво-подростковое, например Рихтера. Классный дядька Рихтер, успешный. Но есть у него много методических провалов.


    W>Gollum >>Ну и "борюсь с Рихтером" — это немного смешно.

    W>]

    Первый вопрос: зачем Вы вывалили это... даже не знаю, как и назвать, в ответ на мой пост? "Программисты, которые предпочитают что-то слащаво-подростковое, например Рихтера", это вроде меня? Если да, то обоснуйте. Что послужило поводом для такого заключения? Может быть, фраза: "Держал в голове рихтеровскую реализацию"?

    W>Согласен, звучит самоутверждающе. Но не будем делать скорополительных выводов, а лучше посмотрим, возможно, для этого действительно есть определенные основания... Дабы исключить искажение смыла переводчиками (а ручаться можно только за себя), я взял и перечитал английское издание книги Applied Microsoft .NET Framework Programming. Вот то, что я понял, и что мне запомнилось.:


    W>Каждый объект, который работает с неуправляемыми ресурсами (например, с файлами или сокетами), должен поддерживать финализацию (finalization). Финализация позволяет ресурсу прибрать за собой во время сборки мусора. Если объект содержит метод Finalize, то он вызывается сборщиком мусора. Если тип, который работает с неуправляемыми ресурсами, не реализует метод Finalize, то это приведет к утечкам памяти. Ресурсы не будут освобождены покуда не завершится поток, их использовавший.


    W>[

    W>Переписка из блога.

    >>>Финализатор имеет смысл только если непосредственно ваш класс хранит в себе Handle внешнего ресурса (за редчайшим исключением).


    W>Очевидно, что именно это и говорит нам Рихтер. Процитирую свой перевод: "Каждый объект, который работает с неуправляемыми ресурсами [skip], должен поддерживать финализацию [skip]." У меня нету сейчас под рукой русского издания, но в этом месте если и возникает разночтение, то только по вине этого самого русского издания. В английском варианте лично для меня тут все достаточно прозрачно.


    W>Тут, между прочим, даже сам Рихтер оговаривается по поводу метода Finalize(), мол, девелоперы не тем боком этот метод юзают, поэтому команда разработчиков компилятора языка C# подумала-подумала, и сделала потенциально опасный код вне закона. Вопрос: это защита от дурака, или от Рихтера? Причем, Рихтер опять же оговаривается, что, в общем-то зря они синтаксис деструктора C# слизали с С++, ведь это только вгоняет сишников в ступор. Опять предупреждение, и не от кого бы то ни было, а от самого Рихтера. А ученики, похоже, просто прохлопали ушами этот момент. Читаем дальше.

    W>]

    W>Если вы знакомы с С++, то сразу заметите, что синтаксис деструктора (этот метод так и называется в спецификации) совпадает с таковым в С++. Тем не менее, Finalize работает совсем не так, как деструктор в С++. ПРИ НАПИСАНИИ СВОЕГО ТИПА ЛУЧШЕ ВОЗДЕРЖАТЬСЯ ОТ FINALIZE.


    W>Дальше можно уже и не комментировать (но я на этом месте не остановился). Я примерил на себя костюм "разрушителей мифов" с канала Discovery, и судя по всему у меня это неплохо получилось. Ну что, миф разрушен?


    W>[

    W>В _очередной_ раз видим необоснованный выпад, и кстати, не только в сторону Джеффри Рихтера...
    W>]

    W>[

    W>Переписка из блога.

    >>>Они похожи на деструкторы C++

    >>>— в результате, программисты пишут и думают себе что-то одно, а получается ОЧЕНЬ другое

    W>Я не знаю, о чем думают программисты, когда пишут свой код, но явно не о Рихтере... И приведенный выше фрагмент в моей интерпретации это полностью доказывает.


    >>>Они вызываются в нефиксированный момент времени

    >>>— при отладке в условиях A мы видим одно поведение, а при реальной работе в условиях B имеем совсем другое

    W>Именно об этом нам и пишет Рихтер. Кратко но _доходчиво_ разъясняя технические аспекты. Вот этот отрывок (это мой литературный перевод, можете cверить с "настоящим" русским изданием, вполне возможно, там содержатся ошибки, которые и ведут к оказиям):


    W>"

    W>Примечание.
    W>В таблице 19-1 обратите внимание, что на аргумент arg1 нашего метода больше никто не ссылается после инструкций процессора со смещением 0x00000020. Это значит, что объект arg1 помечается как "пригодный для сборки в любое время" после выполнения этих инструкций (предполагается, что в приложении больше нет корневых элементов, которые ссылаются на этот объект). Другими словами, как только объект становится недостижимым [чтобы понять смысл этой фразы, нужно читнуть пару абзацев выше, но эти потуги я уже возложу на плечи наших "учеников"], он превращается в кандидата на сборку, поэтому не гарантируется, что объекты будут жить на протяжении всего времени выполнения метода.
    W>[Дальше пошло самое вкусное.]
    W>Одако, когда приложение выполняется через отладчик, или когда сборка помечена атрибутом System.Diagnostics.DebuggableAttribute с параметром isJITOptimizerDisabled выставленным в true, компилятор JIT продлевает время жизни всех переменных (будь то типы, передающиеся по значению или по ссылке) до окончания их области видимости, что в большинстве случаев означает конец самого метода. (Между прочим, компилятор C#, при использовании ключа /debug в командной строке, помечает сборку атрибутом DebuggerAttribute, устанавливая параметр isJITOptimizerDisabled в true.) Это расширение предотвращает сборщика мусора от сборки ссылочных типов во время выполнения кода в данной области видимости, что полезно при отладке. Было бы совсем неуместно, если бы вы вызвали метод объекта, получили неправильный результат, а затем не смогли бы даже взглянуть на этот объект!
    W>"

    W>Рихтер сказал один в один по писаному... Или наоборот.

    W>]

    W>P.S. Рихтер, как известно, на короткой ноге с Microsoft. И я очень сильно сомневаюсь, что кто-то намного лучше самих майкрософтовцев знает, как пользоваться их продуктами. Поэтому бороться если и надо, то не с Рихтером, а с гореучениками, которые не в состоянии уловить мысль человека до конца. Повышать, так сказать, уровень базовых знаний (и в руки Рихтера не давать!). А то человек оперирует таким понятиями, как "функция memcpy", "регистр процессора", хотя для многих "начинающих" это звучит как заклинание. Тогда о каком чтении Рихтера может идти речь? Нужно брать что-то более научно-популярное... Хотя мне кажется, что если читатель толковый, то, дочитав до незнакомого слова, полезет в нет и разберется, что к чему. Это даже способствует повышению уровня своего развития. И не только в сторону освоения .NET. Так что IMHO рано-то Рихтера на свалку истории списывать... Превзойти своего учителя это похвально, вот только не нужно унижать его талант.


    Откуда вы вообще можете знать, позвольте Вас спросить, как я отношусь к Рихтеру, и к тому, что он пишет? Я вообще-то привык всегда подвергать критике и осмыслению то, что пишется и говорится, невзирая на авторитеты. По поводу финализаторов приведу идин из своих постов до этого: http://rsdn.ru/Forum/Message.aspx?mid=1642314&amp;only=1
    Автор: Alexander__S
    Дата: 27.01.06


    W>Alexander__S >>Финлазиторы плохи, спору нет. Но за все надо платить, в том числе и за GC.


    W>Они не плохи. Просто ко всему нужно подходить с головой. Сначала работает голова, и только потом руки. Тогда все будет путем.


    Может быть, укажете примеры использования мной финализаторв с преждевреммой работой рук?
    А финализаторы полохи, не буду сейчас говорить про SafeHandle, но в FW 1.1 я бы постарался избежать их использования. Да об этом и писали уже здесь: http://rsdn.ru/Forum/Message.aspx?mid=1610417&amp;only=1
    Автор: AndrewVK
    Дата: 24.01.06
    Re[8]: Правила использования финалайзеров [blog]
    От: mihailik Украина  
    Дата: 29.01.06 20:55
    Оценка:
    A__>Первый вопрос: зачем Вы вывалили это...

    Скорее, это был ответ на мой начальный пост. Цитаты — оттуда.

    Видимо, eisernWolf читает нас не из древовидного представления.

    Но мысли толковые. Я не согласен, конечно, но всё равно в хорошую сторону подтолкнул. Так что свои баллы я поставил
    Re[7]: Правила использования финалайзеров [blog]
    От: Alexander__S  
    Дата: 29.01.06 20:57
    Оценка:
    Хм... "Разрушитель мифов", поучающий несмышленных программеров, "предпочитающих что-то слащаво-подростковое, например Рихтера"

    Кому бы меня и поучать, извиняюсь, да только не Вам
    Re[20]: Правила использования финалайзеров [blog]
    От: Hacker_Delphi Россия  
    Дата: 30.01.06 05:43
    Оценка:
    Здравствуйте, mihailik, Вы писали:

    M>Тут ты ошибся. Даже не в деталях, а в корне ошибся.


    M>Если твой объект "держит" ссылки на другие управляемые объекты, то финализатор вообще не поможет. Когда твой объект будет мусором, то он уже не будет "держать" никого. Есть ли из него ссылки, нет ли — уже никого не волнует. Мёртвые не потеют.


    M>Если же говорить о частностях, то WeakReference не считаются ссылками и не мешают объектам становится мусором.

    да не держит он никого... вернее тот кого он держит живет однозначно дольше его.
    просто из этого кого-то надо WeakReference убить на уничтожаемый объект — вот и все.
    чтобы в Cache не лежало битых ссылок Конечно, при поиске объекта в Cache я чищу эти битые ссылки, но если можно заранее их почистить....
    Речь идет про финализатор того объекта "на который" есть WeakReference.
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
    Re[21]: Правила использования финалайзеров [blog]
    От: mihailik Украина  
    Дата: 30.01.06 12:01
    Оценка:
    H_D>просто из этого кого-то надо WeakReference убить на уничтожаемый объект — вот и все.
    H_D>чтобы в Cache не лежало битых ссылок

    Нет, это неправильно.

    Финализация накладывает на систему существенные накладные расходы. Такие "подчистки" не оправдывают использование финализации.
    Re[22]: Правила использования финалайзеров [blog]
    От: Hacker_Delphi Россия  
    Дата: 30.01.06 12:37
    Оценка:
    Здравствуйте, mihailik, Вы писали:

    M>Финализация накладывает на систему существенные накладные расходы. Такие "подчистки" не оправдывают использование финализации.


    гы. Если не делать таких чисток — у меня обращения к кэшу будут вызывать море накладных расходов...
    Проверено — так работает быстрее и в случае Application mode GC и в случае Service Mode.
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
    Re[6]: Правила использования финалайзеров [blog]
    От: vdimas Россия  
    Дата: 30.01.06 19:33
    Оценка:
    Здравствуйте, Sinclair, Вы писали:

    S>Здравствуйте, vdimas, Вы писали:

    V>>Потому как доступ к полу disposed в этом случае следовало бы сделать блокируемым. Я понимаю, что вряд ли у кого-то получится явно задиспозить из другого потока в момент финализации, но мало-ли что...
    S>В момент финализации задиспозить ни из какого потока не "вряд ли", а невозможно. Потому что в очередь финализации попадают только те объекты, на которые уже нет ссылок.

    Я имел в виду WeakReference конечно

    V>>Булевская локальная переменная — вполне себе выдержана в духе обычного локального контекста для конкурирующих потоков.

    S>Ты, похоже, смешал в кучу параметр disposing и поле disposed, которые имеют совершенно различный смысл и используются независимо. Перечитай еще раз пример.

    Да нет, не смешал. Еще раз — представь себе ситуацию конкурирующего вызова disposing. Передача булевского флага позволяет обойтись БЕЗ блокировок, ибо со значением false будет вызван только из одного потока.
    Re[23]: Правила использования финалайзеров [blog]
    От: mihailik Украина  
    Дата: 30.01.06 22:31
    Оценка:
    M>>Финализация накладывает на систему существенные накладные расходы. Такие "подчистки" не оправдывают использование финализации.

    H_D>гы. Если не делать таких чисток — у меня обращения к кэшу будут вызывать море накладных расходов...

    H_D>Проверено — так работает быстрее и в случае Application mode GC и в случае Service Mode.

    Если так, то похоже на то, что где-то архитектура кривовата.

    Но раз работает — лучше не трогать
    Re[7]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 31.01.06 04:18
    Оценка:
    Здравствуйте, vdimas, Вы писали:

    V>Я имел в виду WeakReference конечно

    И? Неужели в присутствии WeakReference фреймворк будет вызывать финалайзеры у достижимых объектов? Это что-то новое для меня.
    V>Да нет, не смешал. Еще раз — представь себе ситуацию конкурирующего вызова disposing. Передача булевского флага позволяет обойтись БЕЗ блокировок, ибо со значением false будет вызван только из одного потока.
    Представил. Гонишь. Еще раз перечитай код:
    public void Dispose()
    {
      Dispose(true);
      GC.SuppressFinalize(this);
    }

    Ну и где здесь гарантия невызова из другого потока? Либо я дурак, либо ты что-то очень сильно путаешь.
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[8]: Правила использования финалайзеров [blog]
    От: vdimas Россия  
    Дата: 31.01.06 08:32
    Оценка:
    S>Представил. Гонишь. Еще раз перечитай код:
    S>
    S>public void Dispose()
    S>{
    S>  Dispose(true);
    S>  GC.SuppressFinalize(this);
    S>}
    S>

    S>Ну и где здесь гарантия невызова из другого потока? Либо я дурак, либо ты что-то очень сильно путаешь.

    Сам перечитай еще раз. У нас есть гарантия невызова из другого потока со значением False, т.е. в этом случае можно обойтись без блокировки. А в случае твоего флага _disposed — нужна блокировка во всех случаях.
    Re[9]: Правила использования финалайзеров [blog]
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 31.01.06 09:10
    Оценка:
    Здравствуйте, vdimas, Вы писали:

    V>Сам перечитай еще раз. У нас есть гарантия невызова из другого потока со значением False, т.е. в этом случае можно обойтись без блокировки. А в случае твоего флага _disposed — нужна блокировка во всех случаях.

    Ок, я начинаю понимать твою мысль. Для полноты картины, не мог ли бы ты воспользоваться этим знанием и обойтись без блокировки:
    protected virtual void Dispose(bool disposing)
    {
        if(!this.disposed)
        {
        if(disposing)
        {
            Components.Dispose();
        }
        CloseHandle(handle);
        handle = IntPtr.Zero;
        // Note that this is not thread safe.
        // Another thread could start disposing the object
        // after the managed resources are disposed,
        // but before the disposed flag is set to true.
        // If thread safety is necessary, it must be
        // implemented by the client.
        }
        disposed = true;         
    }
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[24]: Правила использования финалайзеров [blog]
    От: Hacker_Delphi Россия  
    Дата: 01.02.06 09:34
    Оценка:
    Здравствуйте, mihailik, Вы писали:

    M>Если так, то похоже на то, что где-то архитектура кривовата.


    M>Но раз работает — лучше не трогать


    Гм. при чем здесь архитектура?
    WeakReference для того, чтобы GC решал когда Cache надо "подчищать" — вроде бы нормально
    Hashtable для поиска по ID — тоже нормально...
    вычистить "мертвые" ссылки при "смерти" объекта — просто необходимо...
    что не так в архитектуре?
    Да, при более менее таком интенсивном использовании CacheHit составляет примерно 60 % — это при политике Service обслуживания GC.
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
    Re[26]: Правила использования финалайзеров [blog]
    От: Hacker_Delphi Россия  
    Дата: 02.02.06 06:39
    Оценка:
    Здравствуйте, Sinclair, Вы писали:

    S>Здравствуйте, Hacker_Delphi, Вы писали:

    H_D>>Гм. при чем здесь архитектура?
    H_D>>WeakReference для того, чтобы GC решал когда Cache надо "подчищать" — вроде бы нормально
    S>Это верно. Точнее, скажем так: WeakReference — для того, чтобы не удерживать объект.
    H_D>>Hashtable для поиска по ID — тоже нормально...
    H_D>>вычистить "мертвые" ссылки при "смерти" объекта — просто необходимо...
    S>А вот это уже заблуждение. Любое использование слабых ссылок предполагает возможность в любой момент потерять эту ссылку. Проектировать другим способом — нарываться на неприятности. Я вот не могу понять выигрыша от принудительного оповещения всех заинтересованных объектов о смерти слабой ссылки. Неужели вызов IsAlive при каждом обращении так дорог? При этом у тебя финалайзер выполняет работу порядка O() от количества слабых ссылок на умирающий объект. Что чревато нехорошими последствиями.
    Не всех, а ровно одного. Если кто-то держит объект "напрямую" — взял его указатель из Cache — объект не может умереть, а вот если никто не держит — вполне может, все остальные объекты его через Cache дергают.
    H_D>>что не так в архитектуре?
    H_D>>Да, при более менее таком интенсивном использовании CacheHit составляет примерно 60 % — это при политике Service обслуживания GC.
    S>CacheHit, очевидно, никак не зависит от того, в какой момент происходит детектирование пропажи слабой ссылки. Если зависит — то косяк в архитектуре.
    Да, не зависит. А вот затраты на проверку, что ссылки IsAlive достаточно велики. После появления кода финалайзера, который чистит "дохлые" ссылки все заработало гораздо быстрее. И не надо говорить про Bad Design — вопрос в том, что так работает быстрее, а почему оно теоретически должно работать медленнее — меня не волнует.
    ... << RSDN@Home 1.2.0 alpha rev. 0>>
    Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
    Re[5]: Правила использования финалайзеров [blog]
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 04.02.06 00:09
    Оценка:
    Первое предупреждение за оверквотинг.
    ... << RSDN@Home 1.2.0 alpha rev. 637>>
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[8]: Правила использования финалайзеров [blog]
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 04.02.06 00:09
    Оценка:
    Последнее предупреждение за оверквотинг.
    ... << RSDN@Home 1.2.0 alpha rev. 637>>
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[7]: Правила использования финалайзеров [blog]
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 04.02.06 00:55
    Оценка:
    Здравствуйте, eisernWolf, Вы писали:

    W>Ресурсы не будут освобождены покуда не завершится поток, их использовавший.


    Не поток, а процесс.
    ... << RSDN@Home 1.2.0 alpha rev. 637>>
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[10]: Правила использования финалайзеров [blog]
    От: vdimas Россия  
    Дата: 07.02.06 14:00
    Оценка:
    Здравствуйте, Sinclair, Вы писали:

    sorry за запоздалый ответ (упустил эту ветку).

    S>Ок, я начинаю понимать твою мысль. Для полноты картины, не мог ли бы ты воспользоваться этим знанием и обойтись без блокировки:

    S>
    S>protected virtual void Dispose(bool disposing)
    S>{
    S>    if(!this.disposed)
    S>    {
    S>    if(disposing)
    S>    {
    S>        Components.Dispose();
    S>    }
    S>    CloseHandle(handle);
    S>    handle = IntPtr.Zero;
    S>    // Note that this is not thread safe.
    S>    // Another thread could start disposing the object
    S>    // after the managed resources are disposed,
    S>    // but before the disposed flag is set to true.
    S>    // If thread safety is necessary, it must be
    S>    // implemented by the client.
    S>    }
    S>    disposed = true;         
    S>}
    S>


    вот как вариант:
    protected virtual void Dispose(bool disposing) {
        if(!disposing) {    
            // блокировка не нужна
            if(handle!=IntPtr.Zero)
                CloseHandle();
            // нижеследующее нам не нужно
            // handle = IntPtr.Zero;
            // disposed = true;
        } else {
            Components.Dispose();
            // блокировка нужна
            if(!disposed) {
                lock(this) {
                    if(!disposed) { 
                        CloseHandle(handle);
                        handle = IntPtr.Zero;
                        disposed = true;         
                    }
                }
            }
        }
    }


    В общем, финализация без блокировок — это гуд, на мой взгляд.
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.