Q & A On IDisposable and Memory Management
Wasn't this supposed to be easier?

Hi Bill

I am an independent MSCD for Microsoft .NET, and I always enjoy your writing.

Your article beautifully explains the Dispose application implementation pattern. However, there is one important aspect which you do not address and which, in the whole MSDN library, is only documented with one single sentence: "Developers must propagate Dispose throughout a containment hierarchy to ensure that children of a component also free resources".

It took me a lot of research to 1) find this best practice rule and 2) figure out what Microsoft most probably means by it. The words "containment hierarchy", "children" and "component" can mean many different things, depending on whether you look at it strictly from the .NET Framework or from a more general OOP point of view.

In my interpretation, the rule applies strictly to any class who

implements System.ComponentModel.IComponent (such as System.Data.DataSet) and

has children who also implement System.ComponentModel.IComponent (such as System.Data.DataTable) who

depend on the parent through an intermediate class who implements System.Collections.IEnumerable (such as System.Data.DataTableCollection).

Knowing this rule has important consequences. As to the consumers of disposable classes, it saves them a lot of coding because they only have to dispose the DataSet explicitly, but not all the DataTables. The same is true for Forms and their Controls. On the other hand, if a disposable class is not an IComponent, or if a disposable class has dependent objects who are not in an aggregation relationship to the class, they must call Dispose on each and every dependent object explicitly. As to the developers of disposable classes, they must apply additional best practices if their class is an IComponent who in some way contains other enumerable IComponents.

If you check the Internet discussion threads, you will see that many programmers struggle with the best practices regarding IDisposable. I hope that Microsoft will document this more clearly, or maybe you will address this aspect in one of your future articles.

Best regards

Marc

======================== My Response ==========================

Marc,

First, let me address a couple knits: IComponentModel is derived from IDisposable. For that reason, your recommendations about IComponentModel are in line with what I said, only for IDisposable.

Let me address your second point, about disposing only what you need, and exactly what you need. Much of the confusion comes from many developers' internalizing C++ destructor rules. IDisposable is different: it is legal to dispose of an object more than once. As a class author, that means you must handle the case where an object gets is disposed method called multiple times. For your specific example, it is legal to dispose of every DataTable in a DataSet. It's inefficient and unnecessary, but it is legal and will do no harm.

As a class user, it's a little fuzzier. You should Dispose of those objects you "own", ownership being a fuzzy term in .NET. In your example, the DataSet "owns" the DataTables, so the DataSet disposes of them. Your form "owns" the DataSet, and disposes of it. The Form does not own the DataTable, so no extra dispose is needed.

But like I said, ownership in .NET is a bit fuzzy. Consider this snippet:

public void AddSettingsTable( Dataset s )

{

DataTable t = new DataTable( "Settings" );

AddColumns( t );

s.Tables.Add( t );

}

The Dataset, s, owns the table now, even though you created it in your form.

In short, you're right, if "containment" means "members whose lifetime matches the containing object". Further, you should substitute IDisposable for IComponent, as that is more correct.

Thank you for the letter, I'm glad you liked the article.



C# Pro article on Memory Management
The source article on the subject
Created: 4/20/2004 6:11:15 AM

Current Projects

I create content for .NET Core. My work appears in the .NET Core documentation site. I'm primarily responsible for the section that will help you learn C#.

All of these projects are Open Source (using the Creative Commons license for content, and the MIT license for code). If you would like to contribute, visit our GitHub Repository. Or, if you have questions, comments, or ideas for improvement, please create an issue for us.

I'm also the president of Humanitarian Toolbox. We build Open Source software that supports Humanitarian Disaster Relief efforts. We'd appreciate any help you can give to our projects. Look at our GitHub home page to see a list of our current projects. See what interests you, and dive in.

Or, if you have a group of volunteers, talk to us about hosting a codeathon event.