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
Published 20 April 2004 05:11 AM by wwagner
Filed under: ,
Ads by Lake Quincy Media

Comments

No Comments

Search

Go

Blog Group Links

Nascar style badges