J
Jon Skeet [C# MVP]
Laura T. said:Object pooling perhaps?
Yes, that could be a potential use - just one I happen not to have come
across
Laura T. said:Object pooling perhaps?
Hilton said:Just holding a reference to it will keep it alive as it always has.
Hilton
Not necessarily. From the docs for IDisposable:
<quote>
Use this method to close or release unmanaged resources such as files,
streams, and handles held by an instance of the class that implements
this interface. This method is, by convention, used for all tasks
associated with freeing resources held by an object, or preparing an
object for reuse.
</quote>
Note the "or preparing an object for reuse". I can't think of any
examples where that actually *is* the use of IDisposable, but it would
be legal according to the docs.
Doug said:[...]
Whoa, wait. Finalize should NEVER call Dispose to clean up managed
resources, since the maaged resource references may no longer exist!
I don't disagree. But I was just assuming that we were talking about
unmanaged resources here. After all, those are the ones that cause the
most trouble if not disposed properly.
Did I miss something?
For any Compact Framework object containing an Image or a Bitmap it's really
useful, as those classes holdnative resources that you often want to get rid
of as soon as possible in a memory-constrained device.
Also maybe for controlling the lifetime of something in a using{...}
pattern? Maybe?
Brian said:That was a very well thought out response.
Just holding a reference to it will keep it alive as it always has.
Hilton
Hilton said:Sure there is. How would you call Dispose? You'd call it on an object -
right? That means that it would not be GC'd (yet) since you are holding a
reference to it, so everything works just fine as it always has.
Now when
this object can be GC'd (no refs etc), then 'my' logic kicks in, disposes
the object and frees the memory ***IF*** it hasn't already been disposed.
It's just a safety net, not a new paradigm.
Your code is not affected, you can continue to optimize, but the GC will
dispose of any objects that need to be disposed, but weren't. Sounds good
to me.
Doug Semler said:Doug said:[...]
Whoa, wait. Finalize should NEVER call Dispose to clean up managed
resources, since the maaged resource references may no longer exist!
I don't disagree. But I was just assuming that we were talking about
unmanaged resources here. After all, those are the ones that cause the
most trouble if not disposed properly.
Did I miss something?
Huh..*we* may have known that, but some others lurking in the thread
may have interpreted the statement made to mean that it is safe to
call implement a Finalizer that calls Dispose() without regard to
whether the Finalize() method was doing the calling.
I actually like the C++/CLI's compiler's way of "automagically"
implementing the IDisposable pattern if you insert into your classes:
~ClassName()
{
// Dispose managed objects
this->!ClassName(); // call Finalizer
}
!ClassName()
{
// Clean up unmanaged stuff
}
The compiler is nice enough to implement IDisposable, Dispose(bool),
proper calling sequence, and just for good measure a
GC.SuppressFinalize in there on the explicit Dispose call <g>
Your post raises an interesting point which I have often thought about. If
a class implements IDisposable, the developer then has a license to later
add the use of unmanaged resources, and vice versa. For example, one Bitmap
construct uses managed resources and another uses unmanaged resources. But
ignore that for a minute, and let's say that Microsoft originally shipped
the Bitmap class with just one construct that used managed resources and
therefore the class did not (need to) implement IDisposable. Then later on,
they decide that the Bitmap class should use unmanaged resources throughout
for performance (even the construct that only used managed resources) -
they're screwed because exsisting apps won't know (or be able) to call
IDisposable without being recompiled and all apps that used the new .NET
would have this memory leak. Note: I'm just using a hypothetical Bitmap
class as an example here - let's not go off on a tangent speaking about the
actual Bitmap class.
The point is that once a public library class does not
implement IDisposable to free unmanaged resources, it never can (and expect
the right things to happen).
Indeed.
Gee, I've just made a great argument in favor of the OP proposal.
The point is that once a public library class does not
implement IDisposable to free unmanaged resources, it never can (and expect
the right things to happen).
Jon said:I don't see how you have. Why does this fact support the proposal?
Hilton said:Because when the Bitmap get's GC'd, the GC will do a "if (o 'implements'
IDisposable && !o.Disposed) o.Dispose ()" and even those this Bitmap object
won't be Disposed deterministically, it will be Disposed at least when/if an
OutOfMemory exception gets thrown.
Please recall, I'm not saying that my proposal is perfect and that we should
change our code to use if (it requires no code change in the apps). All I'm
saying is that if the GC add the "if" as stated above, it would act as some
level of safety net and catch undisposed objects.
I think we're kidding ourselves to think that you, me, and all the other
.NET engineers in the world will always write code to do the right thing. I
really like "using ()" and use it all the time, but there are some objects
whose lives cannot be bottled up in a few lines. One little bug and whammo,
a LOT of memory potentially gets leaked.
I cannot even count the times
people have posted here about being out of memory only to find that they
didn't know to Dispose a Bitmap object.
The purist in you will jump up and
down and say "well they should have, they screwed up, and they didn't call
Dispose() - their fault.". Now if only we all lived in a perfect world
where one perfect engineer was solely responsible for one perfect project...
However, multiple engineers work on multiple projects and one missing
Dispose() can cost a company millions. Then when we get to finding the
problem, we're back to finding the problem-causing 'malloc-free' we're all
so fond of. :|
Why not add a safety net to make a C# application more robust, less leaky,
stay up longer, etc? Is it a band aid? Absolutely.
3. You could quite easily lock the GC thread. A poorly-designed program
could easily lock on a mutex or event, or pop up a dialog, freezing the GC
thread permenantly or semi-permenantly.
In short ... leave it as-is ... IDisposable and finalizers were fairly
well thought-out and have specific reasons for existing and specific (and
different) limitations on them.
I can't remember seeing that, except for knowing that if you have run
of out Windows handles, GDI+ throws an OutOfMemoryException which gives
the wrong impression. In that situation the GC won't have been called
anyway, so your proposal does no good.