Dispose Again!

  • Thread starter Thread starter Guest
  • Start date Start date
Michael,
This was an answer on Jay, where he told that some classes in this list did
not derive from component.

Small correction again. That was the way I understood Jay's message because
that was in my idea the main part. I readed the unmanaged resources part as
an addition. I start to understand that his meaning about the message was
more about the unmanaged resources part.

Cor
 
Jay B. Harlow said:
IMHO the "set of rules" remains constant, by "set of rules" I mean JD's
three rules which are rather simple. IMHO my list of 3 are more
mantalities for managing JD's three rules...

What would change is the list classes that now either "require" or not
"require" dispose changes. I would expect classes that went from not
requiring Dispose to now requiring Dispose to directly or indirectly to
show up under the "Profiling & various exceptions" clause of my 3 rules...

IMHO, the "set of rules" you refer to are not rules at all; they are
patterns of usage. A rule would tell you, quite simply, "use Dispose() on
object x in situation y" or "don't use Dispose() on object x in situation
z". The "rules" I alluded to are the specific recommendations on usage
using pattern #3.

And I see we didn't even address my question, which is quite simply - and to
use your terms - when the "profiling & various exceptions" clause is
updated, how much time will be spent researching this, updating your usage
patterns, and finally updating any code you've currently completed?

It sounds to me like, to use pattern #3, you have to:

1) Perform a lot of research to determine the Developer's Recommendations,
2) Perform a lot of research to figure out the "various exceptions",
3) Potentially spend a whole lot of time researching and adjusting your code
when the Developer Recommendations change.

From what you and others have posted, this esoteric information on Dispose()
usage is gained through trial and error, from others, and of course
developer recommendations. It appears that there is no definitive "list" of
"classes that now either 'require' or not 'require' dispose", and until
someone puts a definitive list together, it doesn't make a lot of sense to
reference it as if it were a click away. (BTW - If it *is* available, then
this whole thread can be boiled down to a simple link to this definitive
"list"... and shame on whoever knows the whereabouts of this list for not
posting the link already).

At this point I don't see a significant ROI on all this time and energy
spent on trial-and-erroring my way to this sliver of mysterious knowledge,
researching Developer's Recommendations on using Dispose() for every class I
use, or posting a new message every single time I run across an object that
exposes a Dispose() method. After all, I tested the third option with the
SqlCommand object in this thread days ago, and still haven't received a
simple "YES" or "NO" concerning whether or not it should be Disposed of!
Instead I get responses concerning "Labels" and patterns of usage: ("use it
all the time", "use it none of the time", "use it correctly")!

Imagine if you had to stop development for days each and every time you ran
across a new class that exposed Dispose(), so that you could post a
newsgroup message and await a response - which might or might not be
forthcoming. Alas, it's much simpler to consistently Dispose() of my
SqlCommand, SqlConnection and other objects when I'm done with them. I
would love to see a demonstration of how all the proposed research into this
arcane trivia generates anything greater than a personal sense of
accomplishment...
As I've stated before, VB.NET 2005 will get the same "using" statement
that C# has to help manage IDisposable classes...

Good, it's about time.
Hope this helps

Maybe not in the way you think, but thank you nonetheless.
 
Cor,
No that did I not say, because I showed you the message about

Yes! you did say that. :-|

The very first paragraph of:

http://groups-beta.google.com/group/microsoft.public.dotnet.languages.vb/msg/453e201842e0f6b2

States "There is no need to dispose of any object of system.data", end of
paragraph.


The other two paragraphs are hard to follow, but reading it again it appears
you are saying "There is no need to dispose of *most* objects in
system.data. however Connection is one you do need to Dispose". Which is the
point I was trying to make & trying to ask you about...

Jay
 
Michael,
IMHO, the "set of rules" you refer to are not rules at all; they are

Yes its a matter of perspective, not really worth splitting hairs over. :-)

I also consider JD's three & my three both to be "patterns" on one level or
another.

The "real" Dispose/Finalize pattern is the link to the Guidelines that I
posted once or twice in this thread. "Real" in that you should implement it
in your classes that is.

From what you and others have posted, this esoteric information on
Dispose() usage is gained through trial and error, from others, and of
course
I am not disputing that the situation as is, is not good.

1) Perform a lot of research to determine the Developer's Recommendations,
2) Perform a lot of research to figure out the "various exceptions",
3) Potentially spend a whole lot of time researching and adjusting your
code when the Developer Recommendations change.

It really depends on what you define to be a lot. Depending on which
framework object model I am working on, varies how much research and/or
learning I will do. For example System.String & System.Text.StringBuilder I
simply start using (I will review the documentation of specific methods from
time to time to ensure that object/method is a good fit). However the
System.Data namespace I took the time to *learn* (rather then simple
research) how the DataSet object model actually works. I would expect any
Application Architect to do the same (as oppose to simple developers, who
should be working under the guidance of an Application Architect).

Normally I don't seek out exceptions, rather I let the subtle ones find me.
This is not to say that I don't make a note of the exceptions listed on each
method in the MSDN framework reference & plan accordingly...
Imagine if you had to stop development for days each and every time you
ran across a new class that exposed Dispose(), so that you could post a
newsgroup message and await a response - which might or might not be
forthcoming. Alas, it's much simpler to consistently Dispose() of my
I would not stop development to ask! I would go to .NET Framework Reference
on MSDN & find out myself.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/cpref_start.asp

For larger "object models" such as the System.Data namespace I would review
other documentation on how to actually use the types in the namespace, such
books, other MSDN, and other internet articles.

If the class reference was inconclusive, I would decide to use Dispose or
not based on what the class was doing or how much I was using the class. As
has been discussed in this thread it will not really hurt if you call
Dispose when not needed, and usually will not hurt if you don't call Dispose
when needed.

If my program was then exhibiting performance or other negative behavior I
would use CLR profiler to "give it a check up".

Tools such as CLR profiler will identify classes that probably need to have
Dispose called, by virtue of the classes that are hogging the finalization
thread. For example use the "Call Tree View" to "analyze the use of
finalizers, including the number of finalizers executed". If you are
executing finalizers, then you are probably not calling Dispose. The
following article has an example that discusses calling & not calling
SolidBrush.Dispose.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenethowto13.asp

Of course if you are executing finalizers & don't have a Dispose method,
then the class designer probably needs to review the .NET Guidelines on the
Dispose/Finalize pattern...

Hope this helps
Jay
 
Jay B. Harlow said:
The GC will never directly call Dispose! The GC will only directly call
Finalize! Finalize may or may not call Dispose. Normally Dispose &
Finalize will call a common routine.

I think you mentioned "splitting hairs", Jay? Allow me to modify my
statement to the following: The Dispose() method may be called from the
Finalize() routine, which can be called by the GC; which would mean that
it's not necessarily "up to the class user" to "call this method", which was
the actual point.

http://msdn.microsoft.com/library/d.../en-us/cpgenref/html/cpconFinalizeDispose.asp

Hope that helps.

Thanks
 
None of your links provide a definitive list of when to call Dispose() on
classes built into the .NET Framework Library. Not even the one that
describes how to implement Dispose in your own classes.

Based on what you've said, the only reason I can see for dilly-dallying
around Dispose() and not using it every single doggone time is for bragging
rights and self-stroking of one's ego (i.e., "I have this esoteric
knowledge, so I am better than a mere 'programmer'".) The bottom line is
that you have given no substantial reason to waste time researching and
categorizing when to call, and when not to call, Dispose() on classes that
expose it.

As for learning the inner workings of classes in the .NET Framework, I
always thought the entire point of High-Level OO Programming was to provide
programmers with "clock-work" functionality that they could count on to work
consistently without having to know how many "gears were in the box", or the
specific "gear measurements", etc. After all, if everything you've created
relies on the turning of those gears, what do you do with your work when
they switch you over to a digital clock? Case in point, why in the world do
I, while programming VB.NET, need to know that the Framework sets the AH,
BX, CX, DX, SI and DS registers before an INT 21H call in order to open a
file for me?

I was under the impression that the programmer should be shielded from the
inner tinkerings of the class, and that all you really need to -- or
should -- rely on is the fact that "if I passeth in 'X' it shall performeth
'Y' and returneth 'Z'"; and that you shouldn't bet the farm on the internal
workings of a class always achieving their results in the same manner as
they appear to do today. But that's just the "programmer" in me talking,
not "Le Architect".
 
Sorry Cor, but I am quoting you. This is what you said. I responded to it.

You seem to keep trying to elaborate and each time, you seem to contradict
yourself. At this point, I really don't know what you are saying.

My thoughts on this are stated throughout the thread, but to sum up: I
agree that everything doesn't *need* to be disposed (labels), but data
objects most certainly do.
 
Most commonly, there's an awful lot of objects that don't need to be
disposed at runtime but have a visual representation of themselves in
Visual Studio that *does* need to be disposed.

Web controls are the perfect example of that. At design time, they need
to be disposed otherwise you'll squander windows resources. But at
runtime, there's nothing to dispose. Also, if you think about it,
there's no reasonable time for user code to dispose a web control at
runtime (Page.Unload maybe?).

Whoa Dave! Please explain yourself here (and in the paragraphs that
follow). You can't dispose anything at design-time, since these objects
aren't instantiated until run-time. Please don't make this topic even more
confused than it has become. Let's keep design-time out of this completely
as it is irrelevant - objects get instanced at run-time only. Run-time is
what we are talking about. The CLR isn't managing anything at design-time.
This may have been what Cor was getting at earlier. All the standard
System.Data objects: Connections, DataAdapters, DataSets, DataReaders,
none of them need to be disposed at runtime.

Nope, no, sorry, wrong, uh uh, no way, ad nauseum! You absolutely SHOULD
call dispose on OleDbConnections, OleDbDataReaders and OleDbDataAdapters as
these are all connected data objects that may very well be holding pointers
to unmanaged data providers.
It doesn't hurt anything
to call Dispose on them, it just does nothing useful (you *do* have to
close them, and Dispose will call Close for you if necessary, but that's
something else).

Again, sorry, no, nope!
But they all have visual representations that need to
be disposed at design time, so they need to implement IDisposable.

Back to my first comment. Dispose is in absolutley no way related to the
visual design-time work done in VS.NET.
 
Let me split some more hairs... I disagree that it is "not necessarily 'up
to the class user' to "call this method" if you are all interested in having
Dispose fire in a timely manner. Remember that without Dispose, we are at
the mercy of the GC for object clean up. The whole point of Dispose is to
avoid letting finalizes and the GC release unmanaged resources and for us to
take control of this. If we can't have deterministic finalization, we can
at least have deterministic clean-up.

This is the whole point behind Dispose. To even imply that the GC calls
dispose (when, in many situations it won't - even through the finalizer) is
mis-leading.
 
Then there is an imposter posting in this thread under the name "Cor",
because in a reply (in this thread) to David, you wrote:

"There is no need to dispose any object of system.data."

You do go on to say that *sometimes* you exempt the connection object. This
is already a contradiction, and I'm having a very difficult time
understanding why you are saying that you never said this when you clearly
did.
 
Scott M. said:
Let me split some more hairs... I disagree that it is "not necessarily 'up
to the class user' to "call this method" if you are all interested in
having Dispose fire in a timely manner. Remember that without Dispose, we
are at the mercy of the GC for object clean up. The whole point of
Dispose is to avoid letting finalizes and the GC release unmanaged
resources and for us to take control of this. If we can't have
deterministic finalization, we can at least have deterministic clean-up.

This is the whole point behind Dispose. To even imply that the GC calls
dispose (when, in many situations it won't - even through the finalizer)
is mis-leading.

Allow me to re-split your hairs. I said that "The Dispose() method *MAY* be
called from the Finalize() routine" which is completely in line with what
Jay said "The GC will only directly call Finalize! Finalize may or may not
call Dispose."

Of course you said "To even imply that the GC calls dispose (when, in many
situations it won't - even through the finalizer) is mis-leading." Yet, at
the following link,
http://msdn.microsoft.com/library/d.../en-us/cpgenref/html/cpconFinalizeDispose.asp,
which provides guidance from MS on implementing Dispose() in your own
classes, they state:

"Provide implicit control by implementing the protected Finalize Method on
an object (destructor syntax in C# and the Managed Extensions for C++). The
garbage collector calls this method at some point after there are no longer
any valid references to the object."

And the code sample they provide includes the following chunk of code:

Protected Overrides Sub Finalize()
' Simply call Dispose(False).
Dispose (False)
End Sub

So, if it is misleading to say that the GC will call the Finalizer which
*MAY* in turn call Dispose(), why is Microsoft "misleading" us with this
statement and this code?

Are you implying, against MSDN Online, that the Finalizer never calls
Dispose()? Or that the GC never calls the Finalizer? Or are you saying
that even though the GC calls the Finalizer, Dispose() will *never* be
invoked without an explicit call from the user?
 
I don't dispute the article, but what I am saying is that in reality, you
can't guarantee that Finalize will call Dispose in custom class situations
where the finalizer is overriden. It is certainly possible (note: possible,
not probable or even "good idea") that a finalizer won't have a call to
dispose, in which case the GC to Finalizer to Dispose chain is broken and so
the object could be destroyed without doing its clean up.
 
Scott M. said:
I don't dispute the article, but what I am saying is that in reality, you
can't guarantee that Finalize will call Dispose in custom class situations
where the finalizer is overriden. It is certainly possible (note:
possible, not probable or even "good idea") that a finalizer won't have a
call to dispose, in which case the GC to Finalizer to Dispose chain is
broken and so the object could be destroyed without doing its clean up.

Which might just be why they state specifically in their article: "Do not
assume that Dispose will be called. Unmanaged resources owned by a type
should also be released in a Finalize method in the event that Dispose is
not called."

However, if we're going to get into a hair-splitting contest, let's *at the
very least* have an understanding that your statement: "It is certainly
possible (note: possible, not probable or even 'good idea') that a finalizer
won't have a call to dispose" leaves open the possibility that, in spite of
your personal feelings toward Finalize and Dispose, the Finalizer *may* ---
I repeat the word *may* for everyone's benefit here --- *may* call Dipose()!

Now, going back to the whole point of this particular branch of this rather
lengthy discussion: 1) If the GC calls the Finalizer, 2) and the Finalizer
*may*, *may*, *may* call Dispose(), then 3) This means that - despite your
misgivings about the Finalizer *potentially* calling Dispose(), it *may
just* happen. Logically, this would mean that the Dispose() method *might*,
*might*, *might* be invoked without user intervention; indirectly via the
GC, correct?

If we're going to split hairs, let's at least determine which hairs we're
splitting first. Your feeling that a Finalizer should not be trusted to
call Dispose() does not change the *fact* that a Finalizer *might* call
Dispose().
 
Whoa Dave! Please explain yourself here (and in the paragraphs that
follow). You can't dispose anything at design-time, since these objects
aren't instantiated until run-time.

Sorry, but you're wrong.
Please don't make this topic even more
confused than it has become. Let's keep design-time out of this completely
as it is irrelevant - objects get instanced at run-time only. Run-time is
what we are talking about. The CLR isn't managing anything at design-time.

Of course it is. Look, there's not point in talking theoretically.
Create a class, inherit from WebControl, pop up a messagebox in your
constructor and your Dispose override, then add that control to a
WebForm in Visual Studio. You'll see your popup. And you've been in
design-time the whole way.

Inherit from Component, you'll see the same thing.

VS has to instantiate the object, that's how VS works. How else are you
going to get properties, form display, stuff like that? Where do you
think those nice design-time displays come from. (just to note, there
are ways of having other classes handle your display, but it's not
necessary)

Nope, no, sorry, wrong, uh uh, no way, ad nauseum! You absolutely SHOULD
call dispose on OleDbConnections, OleDbDataReaders and OleDbDataAdapters as
these are all connected data objects that may very well be holding pointers
to unmanaged data providers.

I must admit, I meant to type System.Data.SqlClient there. I went into
a bit more detail about the OleDb stuff in another post.
Again, sorry, no, nope!


Back to my first comment. Dispose is in absolutley no way related to the
visual design-time work done in VS.NET.

Okay. You might want to try the exercise I mentioned.

I'm curious, if you don't believe objects are instantiated at
design-time, why do they all inherit from Component in your opinion?
What purpose could that serve at runtime?
 
You are confusing the VS.NET compiler and the CLR and you are making a false
assumption about Dispose based on you mis-interpreted observation.

Your "exercise" only shows what VS.NET does during design-time, not what the
CLR does at run-time and your explanation of why Dispose is there is flat
out wrong. Dispose is not there for the sake of the VS.NET design-time
interface.

Design-time is just that. While components do need to be instanced to
design them, this is a temporary design-time instance and is not comparable
to what is going on at run-time. You've connected two dots that may *seem*
like they are connectable, but in-fact, aren't.
 
I think you are putting words (or opinions) into my mouth when all I was
trying to do was make a point. See inline:

Michael C# said:
Which might just be why they state specifically in their article: "Do not
assume that Dispose will be called. Unmanaged resources owned by a type
should also be released in a Finalize method in the event that Dispose is
not called."

True, but you must acknowledge that in this case, you have no control over
when that *may* happen. Kinda useless if that's the case right?
However, if we're going to get into a hair-splitting contest, let's *at
the very least* have an understanding that your statement: "It is
certainly possible (note: possible, not probable or even 'good idea') that
a finalizer won't have a call to dispose" leaves open the possibility
that, in spite of your personal feelings toward Finalize and Dispose, the
Finalizer *may* --- I repeat the word *may* for everyone's benefit
here --- *may* call Dipose()!

Yep, and that's the same thing I said when I added "(not probable)".
Now, going back to the whole point of this particular branch of this
rather lengthy discussion: 1) If the GC calls the Finalizer, 2) and the
Finalizer *may*, *may*, *may* call Dispose(), then 3) This means that -
despite your misgivings about the Finalizer *potentially* calling
Dispose(), it *may just* happen. Logically, this would mean that the
Dispose() method *might*, *might*, *might* be invoked without user
intervention; indirectly via the GC, correct?

If we're going to split hairs, let's at least determine which hairs we're
splitting first. Your feeling that a Finalizer should not be trusted to
call Dispose() does not change the *fact* that a Finalizer *might* call
Dispose().

I think you are looking for a hair to split on a bald man at this point
since you are just repeating what I said.
 
You are confusing the VS.NET compiler and the CLR and you are making a false
assumption about Dispose based on you mis-interpreted observation.

Your "exercise" only shows what VS.NET does during design-time, not what the
CLR does at run-time

With all due respect, that makes absolutely no sense at all. As far as
the CLR is concerned, it *is* runtime. The CLR couldn't care less what
application is instantiating an object. VS.Net is just another
application in this case.

"Design-time" in this sense is simply an artifact of the Framework
libraries, it's the presence of a few properties in a few base classes.
As far as the CLR is concerned, your code is running, it's runtime.
and your explanation of why Dispose is there is flat
out wrong. Dispose is not there for the sake of the VS.NET design-time
interface.

Design-time is just that. While components do need to be instanced to
design them, this is a temporary design-time instance and is not comparable
to what is going on at run-time.

What's the difference, and what do you think "temporary" means in that
sentence? Is there some kind of special "non-temporary" instantiation
that happens at other times?

It what possible way is it not comparable to runtime?

Your class has been instantiated. The GC will collect your class at
some point. Dispose will be called if you implement it. Various
properties and methods you define will be called. Your code is running,
and you may have aggregated unmanaged resources in your constructor
which means they need to be disposed. Face it, that's runtime.
You've connected two dots that may *seem*
like they are connectable, but in-fact, aren't.

You're long on flat statements, but very short on anything backing them
up.

What's your point exactly? Are you implying that VS.Net *doesn't* need
to call Dispose on custom controls and components instantiated in
designers? Why not?
 
After all, I tested the third option with the
SqlCommand object in this thread days ago, and still haven't received a
simple "YES" or "NO" concerning whether or not it should be Disposed of!

OK, a simple answer. Disposing a SqlCommand does absolutely nothing
except take up time. It's a no-op.

Instead I get responses concerning "Labels" and patterns of usage: ("use it
all the time", "use it none of the time", "use it correctly")!

Imagine if you had to stop development for days each and every time you ran
across a new class that exposed Dispose(), so that you could post a
newsgroup message and await a response - which might or might not be
forthcoming.


I see your general point here, but in practice it's not that tough. In
day-to-day programming, I pretty much deal with only four types of
objects:

Web controls, which never need to be disposed.

Forms controls, which should always be disposed.

Data library objects, and since there's only a few of them I tend to
know the ones I'm working with pretty damn well since I'm hitting the db
all day long, and so I have a pretty good sense as to whether I want to
dispose them and when.

Things that derive from Component, which generally don't need to be
disposed, but it only takes a moment to figure out if the class actually
implements a Dispose function, so in practice that's not a problem.

Alas, it's much simpler to consistently Dispose() of my
SqlCommand, SqlConnection and other objects when I'm done with them. I
would love to see a demonstration of how all the proposed research into this
arcane trivia generates anything greater than a personal sense of
accomplishment...

I actually think avoiding the Dispose calls makes code a lot cleaner.
 
Scott M. said:
I think you are putting words (or opinions) into my mouth when all I was
trying to do was make a point.

Point taken, an I have no need to put words "into your mouth":

"It is up to the class user to call this method [Dispose]."

My original point, as desmonstrated by the Microsoft(tm)-sponsored statement
and code previously posted, is that the Finalize method can call Dispose.
The Finalize method is called via the GC. The GC normally is not invoked by
the "class user". It *can* happen; therefore the statement is False.

"This is the whole point behind Dispose. To even imply that the GC calls
dispose (when, in many situations it won't - even through the finalizer) is
mis-leading."

I'm about to Imply, as Microsoft(tm) has done, this documented fact: The GC
can call Finalize, which *may* indeed call Dispose. There is absolutely
nothing misleading about this fact, and it is well-documented. Now, should
you count on Finalize to call dispose? Absolutely not. But the fact of the
matter is that Finalize *can* indeed call Dispose.

Anything further is fluff.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Back
Top