The First Rule of Implementing IDisposable and Finalizers
• CommentsDon’t do it (unless you need to).
IDisposable
is not a destructor. Remember that .NET has a garbage collector that works just fine without requiring you to set member variables to null.
There are only two situations when IDisposable
does need to be implemented; apply these tests to a class to determine if IDisposable
is needed:
- The class owns unmanaged resources.
- The class owns managed (
IDisposable
) resources.
Note that only classes that own resources should free them. In particular, a class may have a reference to a shared resource; in this case, it should not free the resource because other classes may still be using it.
Here’s a code example similar to what many beginner C# programmers write:
Some programmers (especially with C++ backgrounds) even go a step further and add a finalizer:
The correct implementation of IDisposable
for this type is here:
That’s right, folks. The correct IDisposable
implementation for this class is to not implement IDisposable
! When an ErrorList
instance becomes unreachable, the garbage collector will automatically reclaim all of its memory and resources.
Remember the two tests to determine if IDisposable
is needed (owning unmanaged resources and owning managed resources). A simple checklist can be done as follows:
- Does the
ErrorList
class own unmanaged resources? No, it does not. -
Does the
ErrorList
class own managed resources? Remember, “managed resources” are any classes implementingIDisposable
. So, check each owned member type: - Does
string
implementIDisposable
? No, it does not. - Does
List<string>
implementIDisposable
? No, it does not. -
Since none of the owned members implement
IDisposable
, theErrorList
class does not own any managed resources. - Since there are no unmanaged resources and no managed resources owned by
ErrorList
, it does not need to implementIDisposable
.