July 7, 2004
One of the great features of .NET is the automatic garbage collection that absolves the developer of worrying about C++ style memory management, where for every allocate, there must be a destroy, or you're leaking. And yet, I frequently see overzealous developers write code like this:
Public Function CrazyFunction() As Integer
Dim ds As DataSet = Client.GetDataSet
Dim dr() As DataRow
Select Case _strType
Case "Apple", "Orange"
dr = Client.GetParentRow(ds, _intID)
If Not ds Is Nothing Then ds.Dispose()
At best, this is extra, meaningless code that someone has to debug and read.
At worst, coding like this screams "I'm smarter than the Runtime!" Eg, that the developer somehow knows more about the lifetime and scope of variables than the runtime does. Or that they don't trust the runtime to take care of these mundane scoping disposals. These kinds of developers are, in my experience, dangerous.
The other problem here is the intentional deviation from the default behavior, which is to let the variable fall out of scope naturally. Default behaviors are there to make our lives easier, and to protect us-- they should be leveraged whenever possible.
While there are certainly valid reasons to dispose / close, primarily for objects that have associated "real world" resources like files, database connections, and GDI handles-- that is the exception rather than the rule. Why create extra work for yourself (and the people who will maintain your code) by littering your code with these unnecessary, C++ style Dispose() calls?
Posted by Jeff Atwood
Hi Paul, I found your post on this topic
This brings up a good point. Objects that NEED to be disposed (GDI, files, etc), should have some special visual flag or even generate a "squiggly line" IDE warning when they are NOT disposed in a code block that they just scoped out of.
There seem to be two classes of objects: 1) the common type that can just be GC'ed, 2) the type that require cleanup. I think the distinction is lost on most developers, frankly, and needs to be highlighted by the IDE somehow. If the class implements .Dispose(), then that seems like an easy/obvious way to flag..
"My sample also calls the Clear method, and Dispose when its defined, but separate
tests actually showed they actually did not make a difference -- just set to null.
That said, a colleague has convinced me that not calling Dispose when its defined
is just asking for trouble, afterall why is it defined if not for a good reason."
I think the real lesson here is, don't take anything as gospel, even "best practices" of calling Dispose() -- MEASURE IT YOURSELF and see what is necessary for your application. I'd also add to that, always take the default behavior unless you have a VERY good reason not to, backed by actual data like what you provided in your blog entry (eg, "setting my objects to null keeps the private bytes level at
Paul, great blog entries! Index here:
Here is a good reason : in some companies, code is valued according to the number of lines produced. Of course, perl is highly diregarded in such places, while manual memory management becomes the mark of an "above average programmer".
I have three words for those developers: Obsessive-Compulsive Disorder.
And don't assume that gurus, articles, books, or even MSDN are always correct when they tell you that you don't need a dispose either, since there are a lot of myths that keep getting recirculated here. So while I agree you should typically let the GC do its work (by not setting objects to null), the dispose method exists because the GC won't do all the work in some cases!
IT is a good idea, I’ve followed you! Keep us updated the best deals!
I agree that you shouldn't be setting objects to null (or nothing in VB) unless you really have a damn good reason (and they do exist), but I have to disagree on the dispose. The only objects that should have a dispose method are those that have a reason to have one -- like the files, database connections, and GDI handles. Thus, if there is a dispose method, then you best be using it, and you should wrap it in a try/finally or a C# using block to be sure. True, for those clever enough to decompile things there are some objects with dispose that don't really need them (like the dataset), but you're starting a very dangerous trend if you go down that path. Why? Maybe it will be needed in the future, or maybe someone else maintaining the code won't be so smart -- is it really worth trying to know better than the pattern that exists for a very good reason. And don't assume that gurus, articles, books, or even MSDN are always correct when they tell you that you don't need a dispose either, since there are a lot of myths that keep getting recirculated here. So while I agree you should typically let the GC do its work (by not setting objects to null), the dispose method exists because the GC won't do all the work in some cases!