Tuesday, November 5, 2024

Avoid C# Memory Leaks with Destructor and Dispose

Here are two classes that allocate resources, the first class needs to implement a destructor and Dispose, but the second class doesn’t need to. The difference is that the first class allocates resources in the constructor and doesn’t clean them up immediately. In contrast, the second class allocates resources in a member function and carefully frees them before exiting (using a finally block), so the second class author doesn’t need to bother writing Dispose and a destructor.

class MustDispose
{
public MustDispose()
{
&nbsp create a 3rd party object
&nbsp open a file handle
&nbsp allocate some memory
&nbsp open a database connection
&nbsp open a network port
}
~MustDispose()
{
&nbsp // customized destructor for this class
&nbsp if (3rd party object != null)free the 3rd party object
&nbsp if (file handle != null)close the file handle
&nbsp if (memory != null)free the memory
&nbsp if (connection != null) close the database connection
&nbsp if (port open) close the network port
}
public void Dispose()
{
&nbsp // because this class needs a destructor, it also needs this
&nbsp // idiomatic Dispose method
&nbsp Finalize();
&nbsp System.GC.SuppressFinalize(this);
}
};

class NoDispose
{
public NoDispose()
{
&nbsp // this class has an uninteresting constructor so it doesn't need
&nbsp // a destructor or Dispose
}
MemberFuncThatCleansUp()
{
try
{
&nbsp create a 3rd party object
&nbsp open a file handle
&nbsp allocate some memory
&nbsp open a database connection
&nbsp open a network port
}
finally
{
&nbsp if (3rd party object != null)free the 3rd party object
&nbsp if (file handle != null)close the file handle
&nbsp if (memory != null)free the memory
&nbsp if (connection != null) close the database connection
&nbsp if (port open) close the network port
}
}
}

If a class needs a destructor, you should customize how it is written. However, the Dispose method has become an idiom in C# for any class that needs a destructor:

public void Dispose()
{
&nbsp Finalize();
&nbsp System.GC.SuppressFinalize(this);
}

When to Call Dispose

Call Dispose on an object you create if the class author provides Dispose. Call Dispose as soon as you are done using an object, especially if the object will remain in scope during a lengthy operation or if the object allocates significant resources of its own. If the object you create doesn’t itself allocate significant resources (but how do you know that?) then it might not be a problem to simply let the object go out of scope and have C# call its destructor automatically.

Finally, here’s a C# tip to actually avoid calling dispose:

MustDispose obj = new MustDispose;
try
{
&nbsp // use the object
}
finally
{
&nbsp if (obj != null)
&nbsp&nbsp ((IDisposable)obj).Dispose();
}

You can shorten this up and just write this instead:

using (MustDispose obj = new MustDispose)
{
&nbsp // use the object
}

This assumes that exceptions will be caught at a higher level, which is usually recommended. In other words, don’t catch just to throw.

Scott Zimmerman is an award-winning .NET developer.

scottz1@hotmail.com

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles

Copyright © 2024 · container gardening for beginners. Emailexpertai oto links 1, 2, 3 and 4 & hot bonuses.