How to implement the disposable pattern in a class that inherits from another disposable class?
I often used the disposable pattern in simple classes that referenced small amount of resources, but I never had to implement this pattern on a class that inherits from another disposable class and I am starting to be a bit confused in how to free the whole resources.
I start with a little sample code:
public class Tracer : IDisposable
{
bool disposed;
FileStream fileStream;
public Tracer()
{
开发者_Python百科 //Some fileStream initialization
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
if (fileStream != null)
{
fileStream.Dispose();
}
}
disposed = true;
}
}
}
public class ServiceWrapper : Tracer
{
bool disposed;
ServiceHost serviceHost;
//Some properties
public ServiceWrapper ()
{
//Some serviceHost initialization
}
//protected override void Dispose(bool disposing)
//{
// if (!disposed)
// {
// if (disposing)
// {
// if (serviceHost != null)
// {
// serviceHost.Close();
// }
// }
// disposed = true;
// }
//}
}
My real question is: how to implement the disposable pattern inside my ServiceWrapper class to be sure that when I will dispose an instance of it, it will dispose resources in both inherited and base class?
Thanks.
I have seen this done a couple of ways:
In the derived class override Dispose(bool disposing), cleanup your stuff and then call the base class Dispose(bool disposing). The problem here is the base class already has the disposed gate variable and checks that would would need to be replicated.
Create a protected Cleanup method that Dispose(bool disposing) in the base class calls to actually do the cleanup. The derived class can override it, do it's cleanup, and call the base class Cleanup method. This leaves all of the disposed checks in the base class that don't have to be replicated.
You have some problems firstly you don't define a finalizer yet you call GC.Suppressfinalizer. also you set disposed in the wrong method and on top of that your dispose isn't thread safe.
I use a base disposed class that implements IDispose along with a while host of other helper methods.
public class Disposable : IDisposable
{
private object _lock = new object();
~Disposable()
{
try
{
Dispose(false);
}
catch
{
}
}
protected void ThrowIfDisposed()
{
if (IsDisposed)
{
throw new ObjectDisposedException(GetType().FullName);
}
}
public bool IsDisposed { get; private set; }
protected virtual void Dispose(bool disposing)
{
}
public void Dispose()
{
lock (_lock)
{
if (!IsDisposed)
{
Dispose(true);
IsDisposed = true;
GC.SuppressFinalize(this);
}
}
}
}
Have a look at this blog post by Davy Brion: http://davybrion.com/blog/2008/06/disposing-of-the-idisposable-implementation/
It adds a little extra code to the parent class, but doing appropriate cleanup in the subclass becomes rather simple.
The inherited class, ServiceWrapper, inherits from a class that implements IDisposable, so SericeWrapper also implements IDisposable. For proof, new up an instance of ServiceWrapper. You'll find (with intellisense) that it too has a Dispose() method.
精彩评论