Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using IDisposable to unsubscribe events

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 same event. I need to unsubscribe the old instance from the event first - easy enough. I'd like to do this in a non-proprietary manner if possible, and it seems like this is a job for IDisposable. However, most documentation recommends IDisposable only when using unmanaged resources, which does not apply here.

If I implement IDisposable and unsubscribe from the event in Dispose(), am I perverting its intention? Should I instead provide an Unsubscribe() function and call that?


Edit: Here's some dummy code that kind of shows what I'm doing (using IDisposable). My actual implementation is related to some proprietary data binding (long story).

class EventListener : IDisposable {     private TextBox m_textBox;      public EventListener(TextBox textBox)     {         m_textBox = textBox;         textBox.TextChanged += new EventHandler(textBox_TextChanged);     }      void textBox_TextChanged(object sender, EventArgs e)     {         // do something     }      public void Dispose()     {         m_textBox.TextChanged -= new EventHandler(textBox_TextChanged);     } }  class MyClass {     EventListener m_eventListener = null;     TextBox m_textBox = new TextBox();      void SetEventListener()     {         if (m_eventListener != null) m_eventListener.Dispose();         m_eventListener = new EventListener(m_textBox);     } } 

In the actual code, the "EventListener" class is more involved, and each instance is uniquely significant. I use these in a collection, and create/destroy them as the user clicks around.


Conclusion

I'm accepting gbjbaanb's answer, at least for now. I feel that the benefit of using a familiar interface outweighs any possible downside of using it where no unmanaged code is involved (how would a user of this object even know that?).

If anyone disagrees - please post/comment/edit. If a better argument can be made against IDisposable, then I'll change the accepted answer.

like image 589
Jon B Avatar asked Jan 16 '09 22:01

Jon B


People also ask

How to unsubscribe events in c#?

You cannot easily unsubscribe from an event if you used an anonymous function to subscribe to it. To unsubscribe in this scenario, go back to the code where you subscribe to the event, store the anonymous function in a delegate variable, and then add the delegate to the event.

Why is IDisposable?

Typically, types that use unmanaged resources implement the IDisposable or IAsyncDisposable interface to allow the unmanaged resources to be reclaimed. When you finish using an object that implements IDisposable, you call the object's Dispose or DisposeAsync implementation to explicitly perform cleanup.


2 Answers

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!

like image 127
gbjbaanb Avatar answered Oct 10 '22 09:10

gbjbaanb


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.

like image 39
JaredPar Avatar answered Oct 10 '22 11:10

JaredPar