Forgive me in advance if this question is a little too open-ended, but I've seen similar language discussion posts here so I figured I'd take the plunge.
Anyway, I have read several MSDN help pages and various other blogs on the subject of properly implementing IDisposable classes. I feel like I understand things pretty well, but I have to wonder if there's a flaw in the suggested class structure:
public class DisposableBase : IDisposable
{
private bool mDisposed;
~DisposableBase()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!mDisposed)
{
if (disposing)
{
// Dispose managed resources
mManagedObject.Dispose();
}
// Dispose unmanaged resources
CloseHandle(mUnmanagedHandle);
mUnmanagedHandle = IntPtr.Zero;
mDisposed = true;
}
}
}
Anytime the above is supposed to serve as a base class, you rely on the implementer of the subclass to properly override the Dispose(bool) method where necessary. In short, derived classes must ensure they invoke the base Dispose(bool) method from within their overridden version. If not, the base class' unmanaged resources may never get freed, defeating the primary purpose of the IDisposable interface.
We all know the benefits of virtual methods, but it seems like in this case their design falls short. In fact, I think this particular shortcoming of virtual methods manifests itself frequently when trying to design visual components and similar base/derived class structures.
Consider the following change, using a protected event rather than a protected virtual method:
public class DisposeEventArgs : EventArgs
{
public bool Disposing { get; protected set; }
public DisposeEventArgs(bool disposing)
{
Disposing = disposing;
}
}
public class DisposableBase : IDisposable
{
private bool mDisposed;
protected event EventHandler<DisposeEventArgs> Disposing;
~DisposableBase()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// This method is now private rather than protected virtual
private void Dispose(bool disposing)
{
if (!mDisposed)
{
// Allow subclasses to react to disposing event
AtDisposing(new DisposeEventArgs(disposing));
if (disposing)
{
// Dispose managed resources
mManagedObject.Dispose();
}
// Dispose unmanaged resources
CloseHandle(mUnmanagedHandle);
mUnmanagedHandle = IntPtr.Zero;
mDisposed = true;
}
}
private void AtDisposing(DisposeEventArgs args)
{
try
{
EventHandler<DisposeEventArgs> handler = Disposing;
if (handler != null) handler(this, args);
}
catch
{
}
}
}
With this design, the base class' Dispose(bool) method will always be called, regardless of whether subclasses subscribe to the Disposing event or not. The biggest flaw that I can see with this revised setup is that there is no predetermined order for when event listeners are called. This could be problematic if there are multiple levels of inheritance, e.g. SubclassA's listener might be triggered before its child SubclassB's listener. Is this flaw serious enough to invalidate my revised design?
This design dilemma makes me wish there were some sort of modifier for methods that was similar to virtual but which would ensure that the base class' method was always called, even if a subclass overrode that function. If there's a better way to achieve this, I would greatly appreciate your suggestions.
You're using an event here when really you want to use an inheritance mechanism like virtual. For scenarios like this where I want to ensure my implementation is always called but want to allow for base class customization I use the following pattern
private void Dispose(bool disposing)
if (mDisposed) {
return;
}
if (disposing) {
mManagedObject.Dispose();
}
// Dispose unmanaged resources
CloseHandle(mUnmanagedHandle);
mUnmanagedHandle = IntPtr.Zero;
mDisposed = true;
DisposeCore(disposing);
}
protected virtual void DisposeCore(bool disposing) {
// Do nothing by default
}
With this pattern I've ensured my base class Dispose implementation will always be called. Derived classes can't stop me by simply forgetting to call a base method. They can still opt into the dispose pattern by overriding DisposeCore but they can't break the base class contract.
The derived class can simply re-implement IDisposable and thus prevent your dispose method from being called, so you can't ensure that either.
Personally I wouldn't use either pattern. I prefer building on SafeHandle and similar mechanisms, instead of implementing finalizers myself.
Consider making it apparent that Dispose is not being called so someone will catch it. Of course Debug.WriteLine will only be called when the code is compiled with DEBUG compiler directive defined.
public class DisposableBase : IDisposable
{
private bool mDisposed;
~DisposableBase()
{
if (!mDisposed)
System.Diagnostics.Debug.WriteLine ("Object not disposed: " + this + "(" + GetHashCode() + ")";
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
You can break it down:
A destructor (finalizer) is only needed for unmanaged resources.
Using a Safehandle can turn an unmanged resource into a managed resource.
Ergo: You won't need a destructor. That halves the Dispose pattern.
The reference design uses a virtual void Dispose(bool) to cater for the Base/Derived class problem. This puts the burden on the derived class to call base.Dispose(disposing), the core of your question. I use 2 approaches:
1) Prevent it. With a sealed base-class you won't have to worry.
sealed class Foo:IDisposable
{
void Dispose() { _member.Dispose(); }
}
2) Check it. Like #j-agent's answer but conditional. When performance could be an issue then you don't want the finalizers in Production code:
class Foo:IDisposable
{
void Dispose() { Dispose(true); }
[Conditional("TEST")] // or "DEBUG"
~Foo { throw new InvalidOperation("somebody forgot to Dispose") }
}
The destructor is going to be called no matter if any subclass overrides Dispose() (can be via override or new) but your destructor is going to be called ( ~DisposableBase() ) so i bet putting your logic for cleanup there can be a good starting point.
Here is an intersting article about destructors: http://www.c-sharpcorner.com/UploadFile/chandrahundigam/UnderstandingDestructors11192005021208AM/UnderstandingDestructors.aspx
Related
I am trying to implement the IDisposable pattern on a derived class, and it's not working as expecting to work,
Suppose I have two classes and I want to call the Dispose method of the derived class:
Below is the code of my base class
public class BaseClass : IDisposable
{
// To detect redundant calls
private bool _disposedValue;
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
// TODO: dispose managed state (managed objects)
}
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
// TODO: set large fields to null
_disposedValue = true;
}
}
}
And I've something like this as a derived class
public class DerivedClass : BaseClass
{
// To detect redundant calls
private bool _disposedValue;
// Protected implementation of Dispose pattern.
protected override void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
}
_disposedValue = true;
}
// Call base class implementation.
base.Dispose(disposing);
}
}
And I've some wrapper class
public class WrapperClass : IDisposable
{
public ReadOnlyCollection<BaseClass> Items { get; set;}
// To detect redundant calls
private bool _disposedValue;
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
foreach (var item in Items)
{
item.Dispose();
}
}
_disposedValue = true;
}
}
}
My issue is in the wrapper class, it doesn't call the Dispose method of the DerivedClass, and it calls the Dispose method of the BaseClass instead.
Update
It's my bad, I forget to say that the collections of items were created by NSubstitute like below:
// Having this will not call the Dispose method of the derived class
Items = new ReadOnlyCollection<BaseClass>(new List<BaseClass>
{
Substitute.For<DerivedClass>()
})
// Having this will call the Dispose method of the derived class
Items = new ReadOnlyCollection<BaseClass>(new List<BaseClass>
{
new DerivedClass>()
})
The public implementation of the Dispose() pattern in the documentation is there as an example to handle every case and contingency. It's always "safe" to do the whole thing, but it's also true that most of the time you can skip most of the pattern.
Especially regarding finalizers: you should only need a finalizer if you are creating an original wrapper implementation for a brand new kind of unmanaged resource. Each unmanaged resource type only needs one finalizer, at the root of the IDisposable inheritance tree. And if you don't add a finalizer, you don't need to worry about GC.SuppressFinalize(). Remove that, and some other balls drop as well.
In short, we can reduce the pattern for your DerivedClass all the way down to this:
public class DerivedClass : BaseClass
{
}
This DerivedClass type still provides the Dispose() method and IDisposable implementation inherited from it's parent, and if it doesn't introduce any other unmanaged resources that's all it needs.
My issue is in the wrapper class, it doesn't call the Dispose method of the DerivedClass, and it calls the Dispose method of the BaseClass instead.
When the base.Dispose() calls Dispose(true) the method override in the derived class is executed, which in turn will call base. Dispose(true).
DerivedClass doesn't appear to override Dispose(). Consequently, the base class version is invoked.
Add a public void Dispose() method that calls your protected void Dispose(bool disposing) implementation in DerivedClass.
Let's imagine I have a class named Base with 3 attributes :
class Base : IDisposable
{
private string _String;
private Class1 classe1;
private int foo;
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing)
{
if (disposing)
{
Console.WriteLine("Free Managed ressources");
//HOW TO FREE _String, class1 and foo ?!
}
Console.WriteLine("Free unmanaged ressources");
}
~Base()
{
this.Dispose(false);
}
}
and a classe named Class1 with 2 attributes :
class Class1
{
public int entier { get; set; }
public string Nom { get; set; }
}
My question is : How can I free the attributes of Base in the Dispose method ? (_String, classe1, foo)
My question is : How can I free the attributes of Base in the Dispose
method ? (_String, classe1, foo)
You don't need to, that's the job of the garbage collector. Implementing IDisposable is a way for the framework to let you release any unmanaged resources you have allocated, and dispose managed objects implementing IDisposable themselves (which in turn hold other unmanaged resources).
None of the managed objects at your disposable implement IDisposable, and they will be collected once there is no longer any objects pointing to your Base class. When will that happen? In an arbitrary time, when the GC see's that there is no longer space in generation 0, and it needs to collect. There is nothing you need to do.
Implementing IDisposable does not mean "this object will be collected immediatly once i run Dispose()", it merely means that the framework gives you a chance to reclaim any resources it might not be aware of (such as unmanaged ones). It is a recommended approach, if one implements a finalizer, to suppress the call to it via GC.SuppressFinalize, saving the GC the trouble of moving your object from the Finalizer Queue to the F-Reachable Queue, hence making it available for collection earlier.
when will these 3 attributes free from the heap ? The garbage
collector won't free them because I have GC.SuppressFinalize(this)
You have a basic misunderstanding of how the GC works and what SuppressFinalize means. The GC will run at an non-deterministic time, and you basically shouldn't care when that happens. It's his responsibility to clean up after you. Calling SuppressFinalize on an object implementing a finalizer does nothing more than set a bit in the objects header which the runtime checks when calling finalizers, which will suppress your finalizer from running
In this case, you shouldn't implement IDisposable at all, or if it was there because it was deemed very likely that it could be necessary in the future, then it would have an empty implementation. You certainly shouldn't have a finaliser in there; never have one unless you actually need one with 100% certainty.
There are a few cases where you would want to implement IDisposable, and in some of those cases you'd also want to have a destructor (which is the C# way of having a finaliser).
One is where you have something that it is really important to do when the object is finished with, most often undoing something you have previously done, such as releasing a handle that you'd obtained, closing a connection you'd opened, etc. but not managed memory. (All objects use managed memory, and all objects have their managed memory cleaned up for them if they're can't be used again and more managed memory is needed by something else, that's what the managed in "managed memory" means).
public class SomeClass : IDisposable
{
private IntPtr _someHandle;
public SomeClass(string someIdentifier)
{
_someHandle = GetHandle(someIdentifier);
}
public void Dispose()
{
ReleaseHandle(_someHandle);
}
}
So now whenever something that's been using a SomeClass is done with it, it calls Dispose() on it (perhaps implicitly via a using block) and all is cleaned up nicely.
But what if that doesn't happen? Well, that's why we might have a finaliser:
public class SomeClass : IDisposable
{
private IntPtr _someHandle;
public SomeClass(string someIdentifier)
{
_someHandle = GetHandle(someIdentifier);
}
public void Dispose()
{
ReleaseHandle(_someHandle);
_someHandle = null; // so we know not to release twice.
}
~SomeClass()
{
if(_someHandle != null)
ReleaseHandle(_someHandle);
}
}
So, here if the Dispose() doesn't get called, we still get the clean-up, because the normal garbage-collection process:
Realise you need more memory.
Find objects that aren't going to be used any more.
Reclaim the memory of those objects.
Has the following steps added:
Realise the object whose memory you were going to reclaim has a finaliser to run.
Put the object into a queue of other such objects.
(On a separate thread) run the finaliser of the object.
The object is no longer an object that "has a finaliser to run" as per step 4 above, so next time around it can be reclaimed.
All of this has downsides:
We can't guarantee when, if ever, this will happen.
We didn't get to reclaim as much memory in step 3, because there was such an object.
Garbage collection is generational, and playing nicely with generational collection for an object means either dying quickly or living a long time, dying just after the first time the GC tried to collect an object is pretty much the least optimal time.
We can get around the first two by calling Dispose() rather than letting finalisation happen, which is up to the user of the class, not the class itself. We get around the third by having an object that knows it doesn't need to be finalised mark itself as no longer needing to be:
public class SomeClass : IDisposable
{
private IntPtr _someHandle;
public SomeClass(string someIdentifier)
{
_someHandle = GetHandle(someIdentifier);
}
public void Dispose()
{
ReleaseHandle(_someHandle);
GC.SuppressFinalize(this);
}
~SomeClass()
{
ReleaseHandle(_someHandle);
}
}
If an object has been passed to GC.SuppressFinalize() then step 4 and subsequent don't happen.
The second case where you might what to implement IDisposable is where you have an IDisposable object as a field of another object that "owns" it (controls it's lifetime):
public class SomeOtherClass : IDisposable
{
private SomeClass _someObj;
public SomeOtherClass(string someIdentifier)
{
_someObj = new SomeClass(someIdentifier);
}
public void Dispose()
{
//If base type is disposable
//call `base.Dispose()` here too.
_someObj.Dispose();
}
}
Cleaning up a SomeOtherClass hence means cleaning up the SomeClass it has as a field. Note that here we do not have a finaliser here. We can't need a finaliser, because it would have nothing to do; at best it would do nothing and just have the downsides of finalisers mentioned above, at worse it would try to clean up _someObj without knowing whether this would happen before or after _someObj cleaning itself up and with _someObj queued to clean itself up in a way where it can assume nothing else will do the clean-up.
For the third case, consider if we combine the two cases with a class that has both an unmanaged resource it releases and a field which is a disposable class. Here if we are Dispose()d we want to clean up both, but if we are finalised we want to only clean up the unmanaged resource that is dealt with directly:
public sealed class SomeHybridClass : IDisposable
{
private IntPtr _someHandle;
private SomeClass _someObj;
public SomeHybridClass(string someIdentifier)
{
_someHandle = GetHandle(someIdentifier);
_someObj = new SomeClass(someIdentifier);
}
public void Dispose()
{
ReleaseHandle(_someHandle);
GC.SuppressFinalize(this);
_someObj.Dispose();
}
~SomeHybridClass()
{
ReleaseHandle(_someHandle);
}
}
Now, since there's repetition here, it makes sense to refactor them into the same method:
public sealed class SomeHybridClass : IDisposable
{
private IntPtr _someHandle;
private SomeClass _someObj;
public SomeHybridClass(string someIdentifier)
{
_someHandle = GetHandle(someIdentifier);
_someObj = new SomeClass(someIdentifier);
}
private void Dispose(bool disposing)
{
if(disposing)
{
_someObj.Dispose();
}
ReleaseHandle(_someHandle);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~SomeHybridClass()
{
Dispose(false);
}
}
And for a fourth case, imagine if this class wasn't sealed; it's derived types also need to be able to do this clean-up, so we make the parameterised Dispose(bool) method protected:
public class SomeHybridClass : IDisposable
{
private IntPtr _someHandle;
private SomeClass _someObj;
public SomeHybridClass(string someIdentifier)
{
_someHandle = GetHandle(someIdentifier);
_someObj = new SomeClass(someIdentifier);
}
protected virtual void Dispose(bool disposing)
{
// if this in turn was derived, we'd call
// base.Dispose(disposing) here too.
if(disposing)
{
_someObj.Dispose();
}
ReleaseHandle(_someHandle);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~SomeHybridClass()
{
Dispose(false);
}
}
However, these last two examples are really solving the wrong problems: They're solving the problem of how to have a class that has both a disposable type as a field and an unmanaged resource, and/or be part of a type hierarchy with this happening. Really you're much better off never getting into this situation; either have a class that only deals with an unmanaged resource (and is sealed) or has disposable types in fields, and you end up with only having the deal with the first two cases. If you deal with your unmanaged resources by deriving from SafeHandle then you are really only having to worry about the second case, and that also manages some difficult edge cases too.
Really, finalisers should very, very rarely be written, and when they are written they should be written to be as simple as possible, because there's enough complication inherent to them and the edge-cases around them as it is. You need to know how to deal with overriding protected virtual void Dispose(bool disposing) (note, should never be public) to deal with the legacy of when that had seemed like a good idea to someone, but not have inheritable classes with both unmanaged and managed-disposable resources forcing someone else into that position.
How can I free the attributes of Base in the Dispose method ? (_String, classe1, foo)
As should now be clear, those fields (attributes are a very different thing in .NET) don't need to be freed. The only resource they have is managed memory, so once they can't be reached (aren't in a static, aren't about to have something done to them in a method, and aren't in a field of something that is in either of those categories or a field of something that is in a field in either of those, etc.) their memory will be automatically reclaimed when needed.
Say a factory for SomeDisposable actually is creating/returning a sort of watch dog Wrapper
public class Wrapper : SomeDisposable
{
public new /*:(*/ Dispose() { ... };
}
and the caller uses like
using (SomeDisposable sd = SomeDisposableFactory.Create(...))
{
} // Wrapper.Dispose() never called.
The Wrapper.Dispose() is never called. If Dispose() were virtual then Wrapper.Dispose() would be called.
The IDisposable interface does not guarantee that the other best practice method virtual Dispose(bool) actually exists or enforce that either be virtual so it cannot be generally relied on to exist (it is only a recommended pattern). Interfaces currently do not allow constraints on virtual.
What are some pros and cons for not making the recommended Dispose() pattern virtual which would have solved this particular dilemma. Should C# allow a way of forcing virtual methods via an interface (since abstract classes aren't popular as contract definitions).
No. The pattern actually says that Dispose() (non-virtual) should call a protected virtual void Dispose(bool) method. This guarantees that the base class Dispose call can pass up the hierarchy properly.
This is spelled out in the documentation for IDisposable:
It should provide one public, non-virtual Dispose() method and a protected virtual Dispose(Boolean disposing) method.
The Dispose() method must call Dispose(true) and should suppress finalization for performance.
The base type should not include any finalizers.
This is already solved.
Disposable types which are not sealed should use the common dispose pattern:
public class DisposableResourceHolder : IDisposable
{
private SafeHandle resource; // handle to a resource
public DisposableResourceHolder()
{
this.resource = ... // allocates the resource
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// dispose managed resources.
if (resource != null) resource.Dispose();
}
// free unmanaged resources.
}
}
I have an implementation of an interface, and that interface extends IDisposable. In my particular implementation of the interface, I don't need to dispose anything, so I just have an empty Dispose() method.
public interface IMyStuff : IDisposable
{
}
public MyStuffImpl : IMyStuff
{
public void Dispose()
{
}
}
Now in FxCop, this results in a CA1063:
Error, Certainty 95, for ImplementIDisposableCorrectly
{
Resolution : "Provide an overridable implementation of Dispose(
bool) on 'MyStuffImpl' or mark the type as sealed.
A call to Dispose(false) should only clean up native
resources. A call to Dispose(true) should clean up
both managed and native resources."
}
CriticalWarning, Certainty 75, for CallGCSuppressFinalizeCorrectly
{
Resolution : "Change 'MyStuffImpl.Dispose()' to call 'GC.SuppressFinalize(
object)'. This will prevent derived types that introduce
a finalizer from needing to re-implement 'IDisposable'
to call it."
}
Error, Certainty 95, for ImplementIDisposableCorrectly
{
Resolution : "Modify 'MyStuffImpl.Dispose()' so that it
calls Dispose(true), then calls GC.SuppressFinalize
on the current object instance ('this' or 'Me' in Visual
Basic), and then returns."
}
So, it looks like I can resolve this in one of 2 ways:
Make the class sealed:
public sealed MyStuffImpl : IMyStuff
{
public void Dispose()
{
}
}
Implement part of the typical pattern:
public MyStuffImpl : IMyStuff
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
}
}
In my case, I don't plan on this implementation ever being extended, so I will probably resolve it by making it sealed, but I admit I don't really understand why it matters if it is sealed or not.
Also, just because my class is sealed, FxCop no longer tells me that Dispose() should call GC.SupressFinalize(this); but is that really true? Is it "better" in .NET to just always call SupressFinalize in Dispose regardless?
SuppressFinalize() is meaningless unless your instance has a finalizer.
If your class doesn't have a finalizer, but is not sealed, you should still SuppressFinalize, in case an inherited class adds a finalizer.
Both of your options are correct, except that Dispose(bool) needs to be protected virtual.
In your "implement part of the typical pattern" option, you should make your Dispose(bool) method protected virtual:
protected virtual void Dispose(bool disposing)
{
}
That will provide subclasses an opportunity to handle disposal of any resources they manage. That's the meaning of "overridable" in "Provide an overridable implementation of Dispose(bool)"
Of course, public virtual would also satisfy FxCop.
Edit - New Question
Ok lets rephrase the question more generically.
Using reflection, is there a way to dynamically call at runtime a base class method that you may be overriding. You cannot use the 'base' keyword at compile time because you cannot be sure it exists. At runtime I want to list my ancestors methods and call the ancestor methods.
I tried using GetMethods() and such but all they return are "pointers" to the most derived implementation of the method. Not an implementation on a base class.
Background
We are developing a system in C# 3.0 with a relatively big class hierarchy. Some of these classes, anywhere in the hierarchy, have resources that need to be
disposed of, those implement the IDisposable interface.
The Problem
Now, to facilitate maintenance and refactoring of the code I would like to find a way, for classes implementing IDisposable,
to "automatically" call base.Dispose(bDisposing) if any ancestors also implements IDisposable. This way, if some class higher up in the hierarchy starts implementing
or stops implementing IDisposable that will be taken care of automatically.
The issue is two folds.
First, finding if any ancestors implements IDisposable.
Second, calling base.Dispose(bDisposing) conditionally.
The first part, finding about ancestors implementing IDisposable, I have been able to deal with.
The second part is the tricky one. Despite all my
efforts, I haven't been able to call base.Dispose(bDisposing) from a derived class. All my attempts failed. They either caused
compilation errors or called the wrong Dispose() method, that is the most derived one, thus looping forever.
The main issue is that you cannot actually refer to base.Dispose() directly in your code if there is no such thing as an
ancestor implementing it (be reminded that there might have no ancestors yet implementing IDisposable, but I want the derived code to be ready when and if such
a thing happens in the future). That leave us with the Reflection mechanisms, but I did not find a proper way of doing it. Our code is quite filled with
advanced reflection techniques and I think I did not miss anything obvious there.
My Solution
My best shot yet was to have some conditional code using in commented code. Changing the IDisposable hierarchy would either break the build
(if no IDisposable ancestor exists) or throw an exception (if there are IDisposable ancestors but base.Dispose is not called).
Here is some code I am posting to show you what my Dispose(bDisposing) method looks like. I am putting this code at the end of all the Dispose()
methods throughout the hierarchy. Any new classes are created from templates that also includes this code.
public class MyOtherClassBase
{
// ...
}
public class MyDerivedClass : MyOtherClassBase, ICalibrable
{
private bool m_bDisposed = false;
~MyDerivedClass()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool bDisposing)
{
if (!m_bDisposed) {
if (bDisposing) {
// Dispose managed resources
}
// Dispose unmanaged resources
}
m_bDisposed = true;
Type baseType = typeof(MyDerivedClass).BaseType;
if (baseType != null) {
if (baseType.GetInterface("IDisposable") != null) {
// If you have no ancestors implementing base.Dispose(...), comment
// the following line AND uncomment the throw.
//
// This way, if any of your ancestors decide one day to implement
// IDisposable you will know about it right away and proceed to
// uncomment the base.Dispose(...) in addition to commenting the throw.
//base.Dispose(bDisposing);
throw new ApplicationException("Ancestor base.Dispose(...) not called - "
+ baseType.ToString());
}
}
}
}
So, I am asking is there a way to call base.Dispose() automatically/conditionally instead?
More Background
There is another mechanism in the application where all objects are registered with a main class. The class checks if they implement IDisposable.
If so, they are disposed of properly by the application. This avoids having the code using the classes to deal with
calling Dispose() all around by themselves. Thus, adding IDisposable to a class that has no ancestor history of IDisposable still works perfectly.
The standard pattern is for your base class to implement IDisposable and the non-virtual Dispose() method, and to implement a virtual Dispose(bool) method, which those classes which hold disposable resources must override. They should always call their base Dispose(bool) method, which will chain up to the top class in the hierarchy eventually. Only those classes which override it will be called, so the chain is usually quite short.
Finalizers, spelled ~Class in C#: Don't. Very few classes will need one, and it's very easy to accidentally keep large object graphs around, because the finalizers require at least two collections before the memory is released. On the first collection after the object is no longer referenced, it's put on a queue of finalizers to be run. These are run on a separate, dedicated thread which only runs finalizers (if it gets blocked, no more finalizers run and your memory usage explodes). Once the finalizer has run, the next collection that collects the appropriate generation will free the object and anything else it was referencing that isn't otherwise referenced. Unfortunately, because it survives the first collection, it will be placed into the older generation which is collected less frequently. For this reason, you should Dispose early and often.
Generally, you should implement a small resource wrapper class that only manages the resource lifetime and implement a finalizer on that class, plus IDisposable. The user of the class should then call Dispose on this when it is disposed. There shouldn't be a back-link to the user. That way, only the thing that actually needs finalization ends up on the finalization queue.
If you are going to need them anywhere in the hierarchy, the base class that implements IDisposable should implement the finalizer and call Dispose(bool), passing false as the parameter.
WARNING for Windows Mobile developers (VS2005 and 2008, .NET Compact Framework 2.0 and 3.5): many non-controls that you drop onto your designer surface, e.g. menu bars, timers, HardwareButtons, derive from System.ComponentModel.Component, which implements a finalizer. For desktop projects, Visual Studio adds the components to a System.ComponentModel.Container named components, which it generates code to Dispose when the form is Disposed - it in turn Disposes all the components that have been added. For the mobile projects, the code to Dispose components is generated, but dropping a component onto the surface does not generate the code to add it to components. You have to do this yourself in your constructor after calling InitializeComponent.
Personally, I think you might be better off handling this with something like FxCop. You should be able to write a rule that check so see if when an object is created that implements IDisposable that you use a using statement.
It seems a little dirty (to me) to automatically dispose an object.
There is not an "accepted" way of doing this. You really want to make your clean up logic (whether it runs inside of a Dispose or a finalizer) as simple as possible so it won't fail. Using reflection inside of a dispose (and especially a finalizer) is generally a bad idea.
As far as implementing finalizers, in general you don't need to. Finalizers add a cost to your object and are hard to write correctly as most of the assumptions you can normally make about the state of the object and the runtime are not valid.
See this article for more information on the Dispose pattern.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestDisposeInheritance
{
class Program
{
static void Main(string[] args)
{
classC c = new classC();
c.Dispose();
}
}
class classA: IDisposable
{
private bool m_bDisposed;
protected virtual void Dispose(bool bDisposing)
{
if (!m_bDisposed)
{
if (bDisposing)
{
// Dispose managed resources
Console.WriteLine("Dispose A");
}
// Dispose unmanaged resources
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
Console.WriteLine("Disposing A");
}
}
class classB : classA, IDisposable
{
private bool m_bDisposed;
public void Dispose()
{
Dispose(true);
base.Dispose();
GC.SuppressFinalize(this);
Console.WriteLine("Disposing B");
}
protected override void Dispose(bool bDisposing)
{
if (!m_bDisposed)
{
if (bDisposing)
{
// Dispose managed resources
Console.WriteLine("Dispose B");
}
// Dispose unmanaged resources
}
}
}
class classC : classB, IDisposable
{
private bool m_bDisposed;
public void Dispose()
{
Dispose(true);
base.Dispose();
GC.SuppressFinalize(this);
Console.WriteLine("Disposing C");
}
protected override void Dispose(bool bDisposing)
{
if (!m_bDisposed)
{
if (bDisposing)
{
// Dispose managed resources
Console.WriteLine("Dispose C");
}
// Dispose unmanaged resources
}
}
}
}
If you wanted to use [basetype].Invoke("Dispose"...) then you could implement the function call without the debugger complaining. Then later when the base type actually implements the IDisposable interface it will execute the proper call.
If you wanted to use [basetype].Invoke("Dispose"...) then you could implement the function call without the debugger complaining. Then later when the base type actually implements the IDisposable interface it will execute the proper call.
Try this. It's a one-line addition to the Dispose() method, and calls the ancestor's dispose, if it exists. (Note that Dispose(bool) is not a member of IDisposable)
// Disposal Helper Functions
public static class Disposing
{
// Executes IDisposable.Dispose() if it exists.
public static void DisposeSuperclass(object o)
{
Type baseType = o.GetType().BaseType;
bool superclassIsDisposable = typeof(IDisposable).IsAssignableFrom(baseType);
if (superclassIsDisposable)
{
System.Reflection.MethodInfo baseDispose = baseType.GetMethod("Dispose", new Type[] { });
baseDispose.Invoke(o, null);
}
}
}
class classA: IDisposable
{
public void Dispose()
{
Console.WriteLine("Disposing A");
}
}
class classB : classA, IDisposable
{
}
class classC : classB, IDisposable
{
public void Dispose()
{
Console.WriteLine("Disposing C");
Disposing.DisposeSuperclass(this);
}
}
public class MyVeryBaseClass {
protected void RealDispose(bool isDisposing) {
IDisposable tryme = this as IDisposable;
if (tryme != null) { // we implement IDisposable
this.Dispose();
base.RealDispose(isDisposing);
}
}
}
public class FirstChild : MyVeryBaseClasee {
//non-disposable
}
public class SecondChild : FirstChild, IDisposable {
~SecondChild() {
Dispose(false);
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
base.RealDispose(true);
}
protected virtual void Dispose(bool bDisposing) {
if (!m_bDisposed) {
if (bDisposing) {
}// Dispose managed resources
} // Dispose unmanaged resources
}
}
That way, you are responsible to implement right only the first class which is IDisposable.