C#Dispose(),取消订阅事件

C#Dispose(),取消订阅事件,c#,events,idisposable,unsubscribe,C#,Events,Idisposable,Unsubscribe,在这种情况下,是否可以立即调用dispose并取消订阅事件?context_uu用于管理一个简单的状态机,我们基本上通过创建一个新的状态机来启动和停止它 class ClassA { StateContext context_; void SomeMethod() { if(context_ != null) context_.Dispose(); context_ = new State

在这种情况下,是否可以立即调用dispose并取消订阅事件?context_uu用于管理一个简单的状态机,我们基本上通过创建一个新的状态机来启动和停止它

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
        }
    }

}

除了调用
Dispose
之外,行为良好的对象不需要清理。如果一个对象订阅了可能比它更长寿的其他对象的事件,它必须(表现良好)确保以某种方式清除这些事件。这可以通过使用弱事件或让
Dispose
处理事件订阅来实现


请注意,术语“非托管资源”与术语“非托管代码”的关系很小,并且长期存在的对象的正常事件都是非托管资源。因此,即使事件与非托管代码无关,使用
IDisposable
清除它们也是完全正确的。事实上,我建议,除非存在其他方法来确保清理,否则此类清理应被视为强制性的(例如,事件由弱事件管理器处理,或者订阅事件的对象不会比订阅者更长寿)。WinForms代码通常是草率的,假定事件发布者不会比订阅者长寿,但这并不意味着这种草率应该被认为是可取的。

一个行为良好的对象除了调用
Dispose
之外不应该需要清理。如果一个对象订阅了可能比它更长寿的其他对象的事件,它必须(表现良好)确保以某种方式清除这些事件。这可以通过使用弱事件或让
Dispose
处理事件订阅来实现


请注意,术语“非托管资源”与术语“非托管代码”的关系很小,并且长期存在的对象的正常事件都是非托管资源。因此,即使事件与非托管代码无关,使用
IDisposable
清除它们也是完全正确的。事实上,我建议,除非存在其他方法来确保清理,否则此类清理应被视为强制性的(例如,事件由弱事件管理器处理,或者订阅事件的对象不会比订阅者更长寿)。WinForms代码通常是草率的,假定事件发布者不会比订阅者长寿,但这并不意味着这种草率应该被认为是可取的。

不,您违反了IDisposable合同。违反合同需要额外的关注和严厉的批评。只要类不是公共的,你就可以不受惩罚。如果实际代码与示例代码非常相似,你可以真正简单地将
Dispose
转换为
Unsubscribe
,不实现
IDisposable
,并且仍然具有相同的行为,而无需询问“我是否可以创建符合我想要的逻辑的方法”否,你违反了可识别的合同。违反合同需要额外的关注和严厉的批评。只要类不是公共的,你就可以不受惩罚。如果实际代码与示例代码非常相似,你可以真正简单地将
Dispose
转换为
Unsubscribe
,不实现
IDisposable
,并且仍然具有相同的行为,而无需询问“是否允许我创建符合所需逻辑的方法”“长期对象的正常事件是非托管资源"这是不正确的,;区分非托管资源和托管资源的原因是,在终结期间,接触托管资源可能不安全,因为这些对象可能已经终结。为了在定稿期间取消订阅,触摸我们已订阅的对象可能不安全。因此,只有当disposing为true时才应取消订阅。@TamaMcGlinn:托管资源和非托管资源之间的区别取决于放弃将导致最终履行义务(可能通过最终确定),还是最终未履行义务。如果一个对象从一个长寿命对象订阅了一个普通事件,那么它将不会被最终确定,直到它取消订阅或者长寿命对象符合最终确定的条件。如果长寿命对象在程序退出之前永远不符合终止条件,事件订阅者也不会。@supercat这是否意味着我们应该重写类中的
Finalize
(即
~
)并放置
unsubscribe()
到?@joe:Finalize中的“非托管资源”部分通常不适用于事件,因为事件订阅者在事件发布者的生存期内没有资格进行终结,并且在发布者死后,订阅将变得毫无意义。@supercat我明白了。因此,当有临时订阅者订阅长寿命发布者时,我们应该始终显式调用
Dispose
unsubscribe
。“长寿命对象的正常事件是非托管资源”这是不正确的;区分非托管资源和托管资源的原因是,在终结期间,接触托管资源可能不安全,因为这些对象可能已经终结。为了在定稿期间取消订阅,触摸我们已订阅的对象可能不安全。因此,只有当disposing为true时才应取消订阅。@TamaMcGlinn:托管资源和非托管资源之间的区别取决于放弃将导致最终履行义务(可能通过最终确定),还是最终未履行义务。如果一个对象从一个长寿命对象订阅了一个普通事件,那么它将不会被最终确定,直到它取消订阅或者长寿命对象符合最终确定的条件。如果在程序退出之前,长寿命对象永远不符合终止条件,则事件订阅者也不会。@supercat这是否意味着我们应该覆盖
Finalize
(whic