Are you doing cool stuff? If so, you need to communicate how cool it is, with demo apps, exciting examples, articles, talks, and seminars. I love to bring the best new technologies into the public eye. I'm especially a fan of innovative programming tools and mobility software (Tablet PC, SmartPhone, and .NET Compact Framework). Contact me:
Code, industry analysis, and miscellaneous cross-links from Larry O'Brien, the former editor of Computer Language and Software Development magazines.
To receive an occasional announcement message regarding my seminars or publications, please subscribe to my mailing list.
In a comment on my last post, Alex Peake points out the Dispose() method and the using keyword. This is what I referred to in the post as "implementing IDisposable", but I realize that I glossed over that too fast.
IDisposable is an interface that defines a single method, Dispose(). If you have "valuable resources that have to be put back on the shelf" the recommendation in .NET is that you define your class as implements IDisposable and release the resources in the Dispose() method.
C# goes a step further and provides a keyword, using, that generates a try...finally block and, in the finally block, calls the Dispose() method of the IDisposable object that the using keyword refers to, for instance:
using(myNetworkConnection){doStuff();
throw new EvenIfItThrowsAnException();
} //when execution reaches here, myNetworkConnection.Dispose() will be called
This is how you should get rid of valuable resources, not wait around for the finalizer to be triggered by a call from the garbage collector.
But that raises the question: if IDisposable and Dispose() are the .NET-recommended ways to dispose of non-memory resources, what is the purpose of the finalizer? That is, what are the recommended contents of Object.Finalize() other than a "last chance" call to: if(this is IDisposable) this.Dispose() ? And if those are the intended contents, why not just emit that IL instead?
I read Bryan Flamig's criticism of C# via Loren. Bryan voices a common criticism of C#'s garbage collection (the criticism actually would apply to all languages that don't go beyond the default memory management model of CLR, but let's just continue to use C# as the example): in C++, the timing of when an objects is "cleaned up" is under program control (it's fully deterministic), while in C#, the default behavior is that the timing is non-deterministic (in fact, reclaiming memory is an aspect of "cleaning up" whose precise timing is very explicitly beyond the control of the developer).
Bryan makes the excellent point that "cleaning up an object" certainly means releasing the memory for reuse but can also mean closing a network socket, database connection, file handle, etc. There are many examples of valuable resources such as these that come from a limited pool, and it's perfectly understandable for a programmer to want to control the timing of when such resources are "put back on the shelf," as it were.
In C++, releasing resources and releasing memory are thought of as one event. In C# and most other .NET languages, the act of cleaning up is thought of as being two events: the release of valuable resources (finalization) and the release of memory (destruction). By default, the CLR's garbage collector guarantees that it will call a "finalizer" function prior to releasing an object's memory. So, if you use the finalizer method to control your valuable resources and do nothing else, "cleaning up" is linked to the non-deterministic garbage collector. That's the chief criticism of C#'s garbage collection.
But, to be fair, these non-memory resources are not what garbage collection aims to solve. Garbage collection aims to solve managing physical memory. Allocating and deallocating memory has unique problems (in that memory can point to other memory) and characteristics (the ratio of memory allocations and deallocations to, let's say, the number of file handles opened and closed is approximately a zillion to one). So relying on an algorithm for garbage collection based on physical memory to time the clean-up of your valuable resources is a questionable strategy. But that doesn't mean that garbage collection (of physical memory) is not a great advantage: the garbage collector is fast, it compacts the heap, and it goes a long way to help the most common types of programming bugs in C and C++. It doesn't solve memory management, but it helps a lot.
So if you don't want to rely on the garbage collector to trigger your finalizer to release your valuable resources, what do you do? You implement IDisposable and put the release of valuable resources entirely under programmatic control. Sure, that's an error-prone burden, just like managing physical memory was. But it's a start.
Now, can one imagine a CLR that had an algorithm that was optimized for managing non-memory resources? Yeah, but it might have poor performance. Or can one imagine some in-language facility that provides "deterministic finalization"? Yeah -- C++/CLI will have such a thing and it's certainly on the radar of the designers of the C# language.
But memory management via garbage collection? .NET provides a great implementation of a great idea.
| February 2004 | ||||||
| Sun | Mon | Tue | Wed | Thu | Fri | Sat |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 29 | ||||||
| Jan Mar | ||||||
Recent code:
Recent writing:
Review of Borland's C# Builder 1.0
Recommended .NET Programming Books
Programming Sabre with Java, C#, and XML
Best Practices for .NET Architecture
Windows Server 2003 as an Application Server
Toolroll:
Motion Computing M1200 Tablet PC
Visual Studio 2003 Enterprise Architect
Rational Rose Enterprise Edition 7
T Mobile Pocket PC Phone Edition