I have a class:
public abstract class BaseComponent { ... }
Within the constructor of that class we subscribe to an event handler e.g.
protected ObjectWithEventHandler eventObject { get; private set; }
public BaseComponent (ObjectWithEventHandler obj)
{
eventObject = obj;
eventObject.ChangedEvent += new EventHandler(eventObject_OnChangedEvent );
}
protected void eventObject_OnChangedEvent (object sender, EventArgs e) { ... }
Are there any hard and fast rules when it comes to EventHandler subscription & unsubscription?
Is it considered good practice to provide some clean-up code that unsubscribes the function from the EventHandler? I.e. implement IDisposable and unsubscribe from the EventHandler then?
Or am I worrying unduly?
If you have full control of the usage of BaseComponent and you know that EventObject's lifecycle is shorter or equal* with regard to BaseComponent's lifecycle, you can skip unsubscription code.
In all other cases I would include it. In this case implementing IDisposable is good style.
*) effectively, you are coupling eventObject's lifetime to BaseComponent, so it cannot live shorter, but it could still be equal when the two go out of scope together.
As long as object which exposes event (eventObject) is created inside a BaseComponent class - you can ignore explicit unsubscribing because it will be GCed automatically but explicit unsubscribe is a good practice anyway.
But if you're subscribing for event which exposed by an external object injected into BaseComponent you should implement IDisposable in the BaseComponent class and in the Dispose() method do cleanup.
You should provide some way to trigger unsubscription explicitly if there is any chance that the eventObject might live longer as instances of the classes derived from BaseComponent are supposed to live. Otherwise you would prevent garbage collection of your component, as eventObject holds a reference to it.
Implementing IDisposable() is a good way to accomplish this as long as you can assure that there is some code actually calling it. The finalizer would not call Dispose(), because the garbage collector would not try to clean up your component as long as it is subscribed to eventObject.ChangedEvent and eventObject is still alive.
Related
I have been reading up on memory management and have come across a situation in a project where the book, nor Google has come up with an exact answer. I already know that delegates are manages objects and events are delegate instances. Having said that, delegate instances will be removed from memory once the application ends.
What I can't figure out is how to ensure that external code has freed up all event references by the time my class is disposed (either explicitly or by the GC). As an example, class A exposes an event and class B consumes it. Class B calls Dispose on class A without freeing up references to the delegates. Of course, we cannot throw an error from the Dispose method itself.
Following is a class with a delegate and another one that consumes it.
public class ClassB
{
private ClassA A { get; set; }
public ClassB()
{
this.A = new ClassA();
this.A.OnProcessed += new ClassA.DelegateProcessed(this.ClassA_Processed);
}
public void Process()
{
this.A.Process();
}
public void ClassA_Processed (ClassA sender, EventArgs e)
{
// Do something.
// Code written by another developer does not free up events before calling Dispose.
this.A.Dispose();
this.A = null;
}
}
public class ClassA: IDisposable
{
public delegate void DelegateProcessed (A sender, EventArgs e);
public event DelegateProcessed OnProcessed = null;
~ClassA() { this.Dispose(false); }
public void Dispose ()
{
this.Dispose(true);
System.GC.SuppressFinalize(this);
}
private void Dispose (bool disposing)
{
if (!this.Disposed)
{
if (disposing)
{
// Dispose managed resources here.
// Is it possible / advisable to dispose of delegates / events here?
// Will this adversely affect the consumer class?
this.OnProcessed -= new ClassA.DelegateProcessed(this.ClassA_Processed);
}
}
this.Disposed = true;
}
public void Process () { this.OnProcessed(this, new EventArgs()); }
public void ClassA_Processed (ClassA sender, EventArgs e) { }
}
The point is to ensure that ClassA qualifies for garbage collection no matter what the developer does with ClassB. The point is to minimize the amount of time ClassA spends in memory even if the consumer is careless.
UPDATE: It is clear from the answers that the events do not have to be explicitly removed from ClassA. As for the main question, weak references seem to be the way to go as answered below. The objective is to minimize the time ClassA stays in memory. Please let me know in case I have overlooked anythig.
IDisposable is used to deterministically release unmanaged resources.
There is no need to remove event handlers. For example, if you look at Windows Forms Form and UserControl classes, or ASP.NET Page and UserControl classes, all of which are IDisposable, you'll see extensive use of events, and no special handling during disposal.
Instead of the "classic" Event subscriptions, you should have a look at the Weak Event Patterns.
Event subscriptions may keep objects alive, even if these references are the only references left and the referenced object itself is already gone out of scope. In this case the referenced object will never be collected by the GarbageCollector and stays alive until the end of your application.
This causes serious memory leaks.
If you are using the Weak Events pattern you allow the GabageCollector to better determine if the object is still referenced or if the events are the only references. In this case the objects get collected and your resources get freed.
This section of the code:
private ClassA A { get; set; }
public ClassB()
{
this.A = new ClassA();
this.A.OnProcessed += new ClassA.DelegateProcessed(this.ClassA_Processed);
}
means you have to do nothing.
A B instance owns an A instance and the A has a ref (through the event) to B again.
When a B becomes unreachable then the A will also be collected (GC and circular references).
When the 'A' is Disposed (long) before the B then the 'A' will be collected too (directionality).
The IDispoable interface on A is pointless.
And concerning the implementation:
// class B
this.A.OnProcessed += new ClassA.DelegateProcessed(this.ClassA_Processed);
// in classA
this.OnProcessed -= new ClassA.DelegateProcessed(this.ClassA_Processed);
This won't work, 2 different this means they are 2 different methods.
A properly-written class should in its IDisposable.Dispose method unsubscribe from any events to which it has subscribed. If an object whose event was subscribed has a GC lifetime comparable to the useful lifetime of the object which subscribed (which is a very common case), it won't matter whether the subscription is cleaned up or left dangling. Unfortunately, if A is abandoned without unsubscribing itself from B's event, and something keeps a long-lived reference to B (deliberately or not), anything which keeps B alive will also keep alive A and anything to which A holds a direct or indirect reference (including objects which have active event subscriptions from A). It's very easy to end up with large forests of interconnected objects which will usually become eligible for garbage collection, but which will all have to be kept alive as long as any of them is needed.
It's too bad event subscription and unsubscription are so awkward. If there were an object type associated with events, an object which was going to subscribe to various events could use an "event manager" object to manage subscriptions (so one could say something like MyEventManager.Subscribe(SomeObject.SomeEvent, someProc) and then have MyEventManager.Dispose unsubscribe from all the events to which it had established subscriptions. Unfortunately, there's no decent way to have a method accept an event as a parameter, and thus no way to have a general purpose class to manage incoming subscriptions. The best one could do would probably be to have a CleanupManager class which would take a pair of delegates and be invoked something like `MyCleaner.Register(()=>{SomeObject.SomeEvent += someProc;}, ()=>{SomeObject.SomeEvent -= someProc();}) but that seems rather awkward.
When designing a derived class, are there [dis]advantages to adding a handler to a base class event in the ctor vs overriding the OnEventName() method and adding some behaviour (as well as calling the base method), if one doesn't need to change the base method and doesn't care in what order things happen, but only wants a reusable component with a little extra behaviour?
base class:
public abstract class BaseClass
{
public event EventHandler SomeEvent;
protected void OnSomeEvent(object sender, EventArgs e)
{
// do some stuff
}
}
option A:
public class DerivedA
{
protected override void OnSomeEvent(object sender, EventArgs e)
{
// do some other stuff
base.OnSomeEvent(sender, e);
}
}
option B:
public class DerivedB
{
public DerivedB()
{
SomeEvent += (o,e) => { // do some other stuff };
}
}
There aren't any significant advantages/disadvantages to either approach.
There's a few differences between subscribing to an event vs. overriding a base-class method. For example, if you want some code to run before or after all other handlers, you should really override the OnSomeEvent method, as there's no way to gaurantee that otherwise. But you indicate you don't really care about this.
In general, overriding a method is something that requires a good understanding of the behavior of the base class to ensure that you don't inadvertantly break anything. Subscribing to an event is a less intrusive extensions, and is something that (presumably) the base class designer has planned for.
Sometimes, people argue that performance is better when overriding - but I don't buy this argument. Performance only matters when it matters. The difference here is likely so negligible, that one should be more concerned with simplicity, correctness, and easy of maintenance over performance.
You've already mentioned the order in which things are called. Some other things which admittedly don't happen all that often, but might be significant (based on the fact that the base class controls how the event handlers are invoked):
Event handlers might be called on a different thread;
Under some circumstances, the base class might choose not to call event handlers at all;
The base class might catch specific types of exceptions thrown by handlers; exceptions thrown by your handler might be unintentionally swallowed.
In general, I tend to see events as being there exclusively for a class's users, with a well-designed class having virtual On... methods for subclasses.
This question already has answers here:
Proper use of the IDisposable interface
(20 answers)
Closed 5 years ago.
What is the best practice for when to implement IDisposable?
Is the best rule of thumb to implement it if you have one managed object in the class, or does it depend if the object was created in the class or just passed in? Should I also do it for classes with no managed objects at all?
If you mean unmanaged objects then yes, you should be implementing it whenever you have one or more unmanaged resource you are handling in your class. You should also be using the pattern when you are possibly holding on to objects that are IDisposable themselves, and make sure to dispose of them when your class is disposed.
(agreed that this question has already been asked enough times as to run a small printer out of ink should they be printed...)
While everyone has mentioned (unmanaged) resources, I have another thing to add: I use it when I need to eliminate event handler hookups that would otherwise prevent a class from going out of scope and being garbage collected.
As an example, I have a service which gets injected in to a child view, that child view will subscribe to various async finished type events on the service. The owner of that child view has no idea what the concrete type is, it simply has it as an interface. The service may go out of scope at some arbitrary point in the future, and I don't want it hanging around not being GC'ed. Upon getting rid of that child view, the owner will call Dispose on it to give it the chance to unhook any event handlers. Here is a slightly contrived (and very pseudo code) example, note how the interface for the child view also implements IDisposable.
public class OwnerView {
public OwnerView() {
_childView = new ChildView(myServiceReference);
}
public void CloseChildView() {
if (childView != null) {
_childView.Close();
_childView.Dispose();
}
_childView = null;
}
private IChildView _childView;
}
public class ChildView : IChildView {
public ChildView(MyService serviceRef) {
_serviceRef = serviceRef;
_serviceRef.GetSettingsAsyncFinished += new EventHandler(someEventHandler);
}
public void IDisposable.Dispose() {
_serviceRef -= someEventHandler;
}
private MyService _serviceRef;
}
public interface IChildView : IDisposable {
void DoSomething();
... etc ...
}
There are far more authoritative comments about this from others on SO, like Do event handlers stop garbage collection from occuring? and Garbage collection when using anonymous delegates for event handling. You may also want to check out this codeproject article.
I think the docs are pretty clear about what IDisposable is good for.
The primary use of this interface is
to release unmanaged resources. The
garbage collector automatically
releases the memory allocated to a
managed object when that object is no
longer used. However, it is not
possible to predict when garbage
collection will occur. Furthermore,
the garbage collector has no knowledge
of unmanaged resources such as window
handles, or open files and streams.
It even has an example. In that example the class that implements IDisposable contains a handle. A handle needs to be freed when it no longer used. This is done in the Dispose() method. So the user of that class sees that it implements IDisposable and knows that the class needs to be explictily disposed when it is no longer needed (so the handle can be freed). It is a best practise (i.e. rule) that you should always call Dispose() on IDisosable instances when the instance is no longer needed.
You should implement IDisposable when your class holds resources that you want to release when you are finished using them.
When your class contains unmanaged objects, resources, opened files or database objects, you need to implement IDisposable.
If it has properties which also need to be disposed.
I have the following class
public class Presenter: IDisposable
{
public IView View
{get;private set;}
//snip other object reference, all managed
public Presenter(IView view)
{
View=view;
View.MouseUp += MouseUpEvent;
}
public void MouseUpEvent()
{
//do whatever you want to do on mouse up
}
public void Dispose()
{
View.MouseUp -= MouseUpEvent;
// no more manual disposing
}
}
The question now is, am I implement Dispose() method correctly? Or do I need to manually dispose all the other managed objects just because I have explicilty define Dispose()?
I reckon that the GC is smart enough to do its own disposing ( except the event subscription) even without me manually doing it. Am I right?
If you go with the choice of subscribing in the constructor, then this looks reasonable. I would echo Josh's sentiments that it may not be the best approach. On the other hand, it may be the simplest way of achieving your goal, which is always a good thing. I'm not going to pretend to be an expert on UI patterns: having raised the concern, I'll assume that this is the way you want to work, and address the question itself :)
I personally find Josh's prescribed pattern1 overly complex for simple scenarios - your approach is fine, with just one change: make your class sealed. If you don't want to seal the class, you should go for the Dispose(bool) option (but without the finalizer) because subclasses may also need to dispose of things, and may need a finalizer. Without the possibility of a derived type, life is simpler (as it so often is).
You don't need to do anything with other members just because you now implement IDiposable for that one reason.
So, do you need to derive any further from this class?
1 I do understand that this is the standard recommended pattern, although I'd recommend that you read the advice of Joe Duffy et al for even more details - it can all get very complicated.
Personally, I would avoid hooking/unhooking the event in the constructor and dispose. Instead I would add code to the View get/set accessors and add them there. But if the Presenter is disposed while a View is attached, I would not bother trying to clean that up. You can explicitly detach the View from the presenter if you need explicit detaching.
Having said that, here's what I know about IDisposable.
The recommended approach to implementing IDisposable is to have a protected Dispose(bool) method where you take action. The reason is, you want to distinguish between an explicit disposal and a disposal caused by finalization (garbage collection.)
When you are being disposed because of an explicit Dispose() call, it's ok to touch managed objects and you are expected to dispose of anything you've created that also needs disposing. So you do this only when disposing=true.
But if someone (you) forgets to call Dispose and the finalizer is called, you're being disposed after garbage collection (disposing=false) and you don't want to touch any managed objects because they may already be finalized. The only thing you need to free up in this case is unmanaged resources like Win32 handles and such.
Finally, when Dispose() is explicitly called you'll notice I called GC.SupressFinalize(this) which is a performance hint for the garbage collector. It lets it know that the object doesn't need to be finalized when it is collected. Finalization isn't cheap.
class MyObject : IDisposable {
~MyObject() {
Dispose(false);
}
public void Dispose() {
Dispose(true);
GC.SupressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
if (disposing) {
// dispose of managed resources
}
// dispose of unmanaged resources
}
}
I'm a bit confused about C# Classes and their deconstructor.
I have to consume a few event handlers in a class instance I'm getting in the constructor:
public Foo(IFooHandler handler)
{
handler.Load += Load;
handler.Close += Close;
}
I need to unsubscribe to that event when the Foo class is destroyed. Do I implement IDisposable and unsubscribe in there, or in a deconstructor? I need to consume those events, I can't do it another way.
For one of the classes, I create an instance, check progress, and then the class instance goes out of scope. For another it stays in the MainForm until the form is closed. The first is what I'm worried about because it may still have a reference to that event handler and not properly go.
I don't want to leak memory. When and how should I unsubscribe?
Don't do it in the destructor, because it won't be called while the event handlers are attached : when you attach an instance method of Foo as a handler for an event of Bar, Bar will hold a reference to Foo, so Foo won't be garbage collected, and its destructor won't be called.
You should implement IDisposable, and dispose your object explicitly
public void Dispose()
{
if (handler != null)
{
handler.Load -= Load;
handler.Close -= Close;
}
}
If you ever face the problem of having class A be a long lived class and class(es) B be short lived ones that subscribe to events of class A then you probably would be interested in the Weak Event Pattern. It can be a problem that you do not discover is one until it is to late i.e. Princeton self driving car.