C# Dispose(), отписаться от событий

Можно ли сразу вызывать dispose и отписываться от событий в этом контексте? context_ используется для управления простой машиной состояний, которую мы запускаем и останавливаем, по сути, создавая новую.

class ClassA
{

      StateContext context_;

      void SomeMethod()
      {
         if(context_ != null)
            context_.Dispose();

            context_ = new StateContext();

      }

   class StateContext : IDisposable
   {
        SubClassA()
        {
            //Subscribe to an event
        }   

        void Dispose()
        {
            //unsubscribe to an Event
        }
    }

}

person Thomas Watters    schedule 09.12.2016    source источник
comment
Нет, вы нарушаете контракт IDisposable. Нарушения контракта требуют особого внимания и обстоятельного комментирования. Пока класс не является общедоступным, вам это сойдет с рук.   -  person Hans Passant    schedule 10.12.2016
comment
Если фактический код действительно похож на код примера, вы действительно можете просто превратить Dispose в Unsubscribe, не реализовывать IDisposable, и по-прежнему иметь то же поведение без необходимости спрашивать, разрешено ли мне создавать методы, которые выполняют мою желаемую логику.   -  person SimpleVar    schedule 10.12.2016


Ответы (1)


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

Обратите внимание, что термин "неуправляемый ресурс" имеет минимальное отношение к термину "неуправляемый код" и что обычные события от долгоживущих объектов являются неуправляемыми ресурсами. Таким образом, хотя события не имеют ничего общего с неуправляемым кодом, совершенно правильно и правильно использовать IDisposable для их очистки. В самом деле, я бы предложил считать такую ​​очистку обязательной, если только не существует каких-либо других средств для обеспечения очистки (например, события обрабатываются менеджером слабых событий или объект, на событие которого подписано, не переживет подписчика). Код WinForms часто бывает неряшливым, исходя из предположения, что издатели событий не переживут подписчиков, но это не значит, что такую ​​неряшливость следует считать желательной.

person supercat    schedule 16.12.2016
comment
обычные события от долгоживущих объектов — это неуправляемые ресурсы, это неверно; Причина различия между неуправляемыми и управляемыми ресурсами заключается в том, что во время завершения может быть небезопасно касаться управляемых ресурсов, поскольку эти объекты могут быть уже завершены. Может быть небезопасно прикасаться к объектам, на которые мы подписались, чтобы отказаться от подписки во время финализации. Таким образом, они должны быть отменены только в том случае, если удаление верно. - person TamaMcGlinn; 10.01.2019
comment
@TamaMcGlinn: Различие между управляемыми и неуправляемыми ресурсами основано на том, приведет ли отказ к окончательному выполнению обязательств (возможно, посредством завершения) или к невыполнению. Если объект подписывается на обычное событие долгоживущего объекта, он не будет быть финализирован до тех пор, пока не отпишется или пока долгоживущий объект не станет пригодным для финализации. Если долгоживущий объект никогда не станет пригодным для финализации до тех пор, пока программа не завершит работу, то подписчик на событие тоже этого не сделает. - person supercat; 10.01.2019
comment
@supercat означает ли это, что мы должны переопределить Finalize (то есть ~) в нашем классе и поместить unsubscribe() в часть «неуправляемого ресурса» в Шаблон IDisposable ? - person joe; 09.05.2019
comment
@joe: Finalize обычно не работает с событиями, потому что подписчик события не получит право на финализацию в течение всего срока существования издателя события, а после смерти издателя подписка станет спорной. - person supercat; 09.05.2019
comment
@supercat Я понимаю. Таким образом, мы всегда должны явно вызывать Dispose для unsubscribe, когда есть временный подписчик, который подписывается на долгоживущего издателя. - person joe; 10.05.2019