Using IDisposable to unsubscribe events

前端 未结 9 2131
广开言路
广开言路 2020-11-28 05:52

I have a class that handles events from a WinForms control. Based on what the user is doing, I am deferencing one instance of the class and creating a new one to handle the

9条回答
  •  时光说笑
    2020-11-28 06:27

    From all that i read about disposables i would argue that they were really mainly invented for solving one problem: freeing unmanaged system resources in a timely manner. But still all examples that i found are not only focussed on the topic of unmanaged resources, but also have another property in common: Dispose is called just to speed up a process that otherwise would have occured later on automatically (GC -> finalizer -> dispose)

    Calling a dispose method that unsubscribes from an event however would never occur automatically, even if you would add a finalizer that would call your dispose. (at least not as long as the event owning object exists - and if it would be called you wouldn't benefit from the unsubscription, since the event owning object would also be gone anyway)

    So the main difference is that events somehow build an object graph that can't be collected, since the event handling object suddenly becomes referenced of the service that you just wanted to reference/use. You suddenly are forced to call Dispose - no automatic disposal is possible. Dispose would thereby get a subtle other meaning than that found in all examples where a Dispose call - in dirty theory ;) - isn't necessary, since it would get called automaically (at some time)...

    Anyway. Since the disposable pattern is something that already is pretty complicated (deals with finalizers that are hard to get right and many guidelines / contracts) and more importantly in most points has nothing to do with the event back referencing topic, i would say it would be easier to get that separeted in our heads by just not using that metaphor for something that could be called "unroot from object graph" / "stop" / "turn off".

    What we want to achieve is to disable / stop some behaviour (by unsubscribing from an event). It would be nice to have a standard interface like IStoppable with a Stop() method, that by contract is just focussed on

    • getting the object (+ all its own stoppables) disconnected from events of any objects that it didn't create by its own
    • so that it won't get called in implicit event style manner any longer (therefore can be perceived as stopped)
    • can be collected as soon any traditional references onto that object are gone

    Let's call the only interface method that does the unsubscription "Stop()". You would know that the stopped object is in a acceptable state but only is stopped. Maybe a simple property "Stopped" would also be a nice to have.

    It even would make sense to have an interface "IRestartable" that inherits from IStoppable and additionally has a method "Restart()" if you just want to pause a certain behaviour that certainly will be needed again in the future, or to store a deleted model object in a history for later undo recovery.

    After all writing i have to confess to have just seen an example of IDisposable somewhere over here: http://msdn.microsoft.com/en-us/library/dd783449%28v=VS.100%29.aspx But anyway until i get every detail and the original motivation of IObservable i would say it is not the best use case example

    • since again it is a pretty complicated system around it and we only have a small problem over here
    • and it might be that one of the motivations of that that whole new system is to get rid of events in the first place, which would result in a sort of stack overflow concerning th e original question

    But it seems they are on some right track. Anyway: they should have used my interface "IStoppable" ;) since i strongly believe there is a difference in

    • Dispose: "you should call that method or something might leak if the GC happens to late" ....

    and

    • Stop: "you have to call this method to stop a certain behaviour"

提交回复
热议问题