Friday, June 22, 2007

avoid finalizers/use "using"

this is something we’ve gotten wrong a bit in places: in c#, only use a finalizer (i.e. a ~ClassName() method) if you need to clean-up unmanaged resources you’ve allocated. the reason for this is that if your class has a finalizer, the garbage collector will place it in the finalization queue and will not release it immediately. if you do have unmanaged resources and require a finalizer, implement IDisposable and do your cleanup in a shared Dispose(bool isDisposing) method. make sure to call GC.SuppressFinalize() in your Dispose() method so that if your client has already called Dispose(), your object is not placed in the finalization queue. for example:

public class ClassName : IDisposable
{

private bool m_IsDisposed;

~ClassName()
{

Dispose(false);

}

public void Dispose()
{

Dispose(true);

GC.SuppressFinalize(this);

}

public void Dispose(bool FromDisposeMethod)
{

if (!m_IsDisposed)
{

m_IsDisposed = true;

if (FromDisposeMethod)
{

//release managed resources; only do this if from Dispose method since they themselves might have been finalized

//...

}

//release unmanaged resources

//...

}

}

}

also, use "using" as much as possible. you can do this with any object that implements IDisposable:

using (MemoryStream ms = new MemoryStream())
{

//do whatever you want with ms

//...

}

using will automatically call Dispose() when the scope of this block ends, so you get very readable code and know that resources are properly released--

No comments: