Yes, go for it. Although some people think IDisposable is implemented only for unmanaged resources, this is not the case - unmanaged resources just happens to be the biggest win, and most obvious reason to implement it. I think its acquired this idea because people couldn't think of any other reason to use it.
Its not like a finaliser which is a performance problem and not easy for the GC to handle well.
Yes, go for it. Although some people think IDisposable is implemented only for unmanaged resources, this is not the case - unmanaged resources just happens to be the biggest win, and most obvious reason to implement it. I think its acquired this idea because people couldn't think of any other reason to use it.
Its not like a finaliser which is a performance problem and not easy for the GC to handle well. Put any tidy-up code in your dispose method. It'll be clearer, cleaner and significantly more likely to prevent memory leaks and a damn sight easier to use correctly than trying to remember to un-do your references.
The intention of IDisposable is to make your code work better without you having to do lots of manual work. Use its power in your favour and get over some artificial "design intention" nonsense. I remember it was difficult enough to persuade Microsoft of the usefulness of deterministic finalisation back when .
NET first came out - we won the battle and persuaded them to add it (even if it was only a design pattern at the time), use it!
I strongly disagree. You are breaking the "contract" in "design by contract" when you do that. – Domenic Jan 17 '09 at 0:05 2 what contract?
Nowhere does it say "IDisposable is for unmanaged resources only". Often it says "can be used for" but that's quite a difference. – gbjbaanb Jan 17 '09 at 1:29 1 @Domenic: I agree with gbjbaanb.
Even if the docs did say that IDisposable is intended only for the release unmanaged resources, you wouldn't really break any hard contract (as in preconditions, postconditions and class invariants) when you use it for other clean-up. – Andreas Huber Jan 17 '09 at 8:24 Wouldn't letting go of listeners be considered cleaning up? – toast Jan 17 '09 at 15:30 I've pondered the same question as the OP and have sort of decided somewhere along the line to allow uses other than unmanaged resource cleanup but from what I can tell most documentation strictly directs developers to use IDisposable pattern to dispose of unmanaged or managed resources.
I can't find the link but somewhere, managed resources have been described as managed objects that own resources either managed or unmanaged which also implement IDisposable. Whether divergence from these recommendations is considered dangerous or bad practice I'm not yet sure. – jpierson Jan 17 '09 at 5:02.
My personal vote would be to have an Unsubscribe method in order to remove the class from events. IDisposable is a pattern intended for deterministic release of unmanaged resources. In this case you not managing any unmanaged resources and therefore should not be implementing IDisposable.
IDisposable can be used to manage event subscriptions but probably shouldn't. For an example I point you to WPF. This is a library rife with events and event handlers.
Yet virtually no class in WPF implements IDisposable. I would take that as an indication that events should be managed another way.
3 WPF has hardly any IDisposable controls because it uses the WeakEvent Pattern to get round leaks: msdn.microsoft.com/en-us/library/aa97085... – gbjbaanb Jan 17 '09 at 1:34 @gbjbaanb - Right thats what I understood as well although this probably backs up what JaredPar's point was about "an indication that events should be managed another way". One of those ways I suppose could be the WeakEvent Pattern, another would be a custom IUnsubscribable interface for example that could mimic how IDisposable is used. – jpierson Apr 14 '11 at 5:07.
One thing that bothers me about using IDisposable pattern for unsubscribe from events is Finalization issue. Dispose() function in IDisposable is supposed to be call by the developer, HOWEVER, if it isn't called by the developer, it is a understood that the GC will call this function (by the standard IDisposable pattern, at least). In your case, however, if you don't call Dispose() no one else will - The event remains and the strong reference holds GC from calling the finalizer.
The mere fact that Dispose() won't be called automatically by GC seems to me enough to not to use IDosposable in this case. Perhaps it calls for a new application specific interface that says that this type of object must have a Cleanup function called to be disposed by GC.
Jason Coyne: I would join with Jason Coyne in arguing just the opposite: iDisposable is for things which cannot be satisfactorily handled via garbage collection alone. Indeed, my interpretation of the iDisposable contract would be: the /only/ objects which /shouldn't/ implement iDisposable are those for which GC-based cleanup is sufficient, or possibly those which can't be cleaned up with a single method call. To my mind, the /non-implementation/ of iDisposable makes a stronger statement than the implementation of it.
– supercat Nov 1 '10 at 18:34 1 After a while with my code, I tend to agree with you. However, I am still concerned about the ambiguity of IDisposable and wish Microsoft handled the issue better. – VitalyB Nov 2 '10 at 8:08 I totally agree with you.
IDisposable was implemented from the very beginning to handle COM interop and integration with unmanaged resources. Having provided a solution that guarantees no memory leaks is good, but as you noted, if you're using Dispose() to unsubscribe from events and you don't call the method directly in code (i.e. A "using" statement or otherwise), then a strong reference is held and the object never gets GC'ed.It's a pain in the rear, and definitely something to bring up.
– Doug Nov 20 '10 at 5:15.
I think disposable is for anything that GC can't take care of automatically, and event references count in my book. Here is a helper class I came up with. Public class DisposableEvent : IDisposable { EventHandler Target { get; set; } public T Args { get; set; } bool fired = false; public DisposableEvent(EventHandler target) { Target = target; Target += new EventHandler(subscriber); } public bool Wait(int howLongSeconds) { DateTime start = DateTime.
Now; while (!fired && (DateTime. Now - start). TotalSeconds Sleep(100); } return fired; } void subscriber(object sender, EventArgs e) { Args = e.
Value; fired = true; } public void Dispose() { Target -= subscriber; Target = null; } } which lets you write this code : Class1 class1 = new Class1(); using (var x = new DisposableEvent(class1. Test)) { if (x. Wait(30)) { var result = x.
Args; } } One side effect, you must not use the event keyword on your events, since that prevents passing them as a parameter to the helper constructor, however, that seems to not have any ill effects.
Another option would be to use weak delegates or something like WPFs weak events, instead of having to unsubscribe explicitly. P.S. OT I consider the decision to only provide strong delegates the single most expensive design mistake of the . NET platform.
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.
I disagree. There is a strong convention that if an object requires cleanup, its owner can clean it up by trying to cast to IDisposable and, if that works, calling Dispose. One shouldn't have to guess whether an object might require some other type of cleanup.
While it's true that many disposable objects will manage to clean up for themselves if abandoned, the implication that an object which implements IDisposable will clean up for itself when abandoned is far weaker than the implication that an object which doesn't implement IDisposable will do so. – supercat May 4 '11 at 22:12 Incidentally, I think the MS default IDisposable pattern is silly (the only objects with cleanup finalizers should be those whose purpose is to encapsulate a single cleanup responsibility; if a class does something other than handle a single cleanup responsibility, then by definition any derived classes will as well, and thus derived classes should not have finalizers for cleanup (they may have finalizers generate "Object wrongfully abandoned" log entries). I would also note that the name "Dispose" is a misnomer, since the purpose isn't to dispose of an object, but rather... – supercat May 4 '11 at 22:15 ...to allow it to carry out any responsibilities it has (typically the cleanup of other objects) before it is abandoned.
– supercat May 4 '11 at 22:16.
IDisposable is firmly about resources, and the source of enough problems to not muddy the waters further I think. I'm voting for an Unsubscribe method on your own Interface too.
One option may be not to unsubscribe at all - just to change what the subscription means. If the event handler could be made smart enough to know what it's meant to do based on the context, you don't need to unsubscribe in the first place. That may or may not be a good idea in your particular case - I don't think we've really got enough information - but it's worth considering.
2 In my case I think it means the object would live forever and I'd have a memory leak, unfortunately. – Jon B Jan 16 '09 at 23:43 @Jon B - I think this is was happens with most non-UI events. +1 – Doug Nov 20 '10 at 5:17 Just in case John's explanation wasn't clear I think what he is suggesting is that in some cases like this objects can be recycled instead of thrown away for a new instance.
This allows the existing event subscriptions to be used without having to detach. Think of it like a thread pool or connection pool for your objects where there are a pool of possible ones that can be recycled. It's not a solution for all situations but probably in more than cases than not if you just change how your thinking about it.
– jpierson Apr 14 '11 at 5:23.
One thing that bothers me about using IDisposable pattern for unsubscribe from events is Finalization issue.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.