>> I suppose this is the crux of the problem, and it's my question. How
>> can I create my class that will automatically call Close() when the
>> object goes out of scope and needs to be garbage collected.
>
> You can't do that. Nothing happens when an object goes out of scope.
>>> I'm still new to C#, but it's impossible to create a class that can
>>> dispose of itself?
[quoted text clipped - 8 lines]
> thing by hand with a try-finally block, but the compiler will do this
> for you if you can use a using statement.
That is correct. To furter clarify this, it's only the object that you
specify in the using clause that is disposed, any other objects that
happen to have the using block as scope doesn't get disposed.
Example:
using (StreamWriter writer = File.CreateText("info.txt)) {
String message = "Hello world.";
writer.Write(message);
}
Here the string message has the using block as scope. Still, only the
StreamWriter will be disposed, but not the string. (Yes, I know that
strings doesn't implement IDisposable, but it's just an example...)
>>> What about instances where the programmer forgets to call Dispose()
>>> on the object they're using. In this case, the Close() method will
[quoted text clipped - 6 lines]
>
> Is a finalizer really a backup to Dispose?
Yes, it's used that way.
> I've never heard that before
> and question how it could be used that way. I mean, you have no idea
> when a finalizer will be called so what can it do of any use since it
> will not know the state of any unmanaged resources by the time the
> finalizer runs?
The Dispose method will call GC.SuppressFinalize, so the finalizer will
only run if Dispose was not called.
You can check out the example code for the IDisposable interface:
http://msdn2.microsoft.com/en-us/library/system.idisposable.aspx
> I don't think I've ever written a finalizer, especially
> not one that has anything to do with the IDispose pattern.
[quoted text clipped - 11 lines]
> When db goes out of scope, the compiler has emitted code to cause the
> object's Dispose method to be called.
The compiler adds the code at the end of the using block. This has
nothing at all to do with the scope of the variable. If the scope of the
variable is outside the using block, the code is still added at the end
of the using block:
CDB db = new CDB()
using (db) {
...
// Dispose is called here
}
// the db variable is still reachable here
> So he would implement the IDispose
> pattern to cause Close (i.e., Dispose) to be called when all the
> references to the object have gone out of scope.
The Dispose method has to be called explicitly (for example by using
using). It's not called automatically when the object gets unreachable.
> (Of course, as already
> pointed out, the IDispose pattern need not be implemented unless
[quoted text clipped - 3 lines]
> have gone out of scope, that doesn't mean anything about when the GC
> will get around to cleaning up that object?
I just mean that nothing happens when an object goes out of scope (or to
be more accurate, when the reference variable goes out of scope).

Signature
Göran Andersson
_____
http://www.guffa.com
GlennDoten - 16 Aug 2007 14:20 GMT
>>>> I'm still new to C#, but it's impossible to create a class that can
>>>> dispose of itself?
[quoted text clipped - 23 lines]
> StreamWriter will be disposed, but not the string. (Yes, I know that
> strings doesn't implement IDisposable, but it's just an example...)
Agreed. In that case you'd use this:
using (StreamWriter writer = File.CreateText("info.txt))
{
using (string message = "Hello world.")
{
writer.Write(message);
}
}
(Again, as you said, a string is not disposable, but pretend it is.)
>> I've never heard that before and question how it could be used that
>> way. I mean, you have no idea when a finalizer will be called so what
[quoted text clipped - 3 lines]
> The Dispose method will call GC.SuppressFinalize, so the finalizer will
> only run if Dispose was not called.
Ah yes, now that you mention that. I forgot about SuppressFinalize.
>>>> I suppose this is the crux of the problem, and it's my question.
>>>> How can I create my class that will automatically call Close() when
[quoted text clipped - 20 lines]
> }
> // the db variable is still reachable here
The code isn't added to the end of the using block, at least not like
that. The compiler automatically emits a finally block. So while "going
out of scope" is not technically correct, what I meant was that the db
variable is *effectively* out of scope once the finally block runs; that
is, the Dispose method has been run on the object once the scope of the
using block ends. I didn't mean to say the object referred to by the db
variable would be eligible for garbage collection after the using block
is finished, just that the Dispose method is guaranteed to have been
called at that point.
>> So he would implement the IDispose pattern to cause Close (i.e.,
>> Dispose) to be called when all the references to the object have gone
>> out of scope.
>
> The Dispose method has to be called explicitly (for example by using
> using). It's not called automatically when the object gets unreachable.
Well, to nit-pick, I would say that using the using statement calls the
Dispose method implicitly.
Again, I hope I haven't given the impression that Dispose is called
somehow once all the references to it go out of scope.
>> Or do you mean that the just because all the references to an object
>> have gone out of scope, that doesn't mean anything about when the GC
>> will get around to cleaning up that object?
>
> I just mean that nothing happens when an object goes out of scope (or to
> be more accurate, when the reference variable goes out of scope).
Except that it may make the object referenced by the variable eligible
to be garbage collected ("may" because other variables may hold
references to the object as well). But as far as Dispose is concerned,
agreed, nothing happens when a variable referencing an object goes out
of scope.
Phew, I think we're saying the same thing!

Signature
-glenn-
Peter Duniho - 16 Aug 2007 17:56 GMT
> Agreed. In that case you'd use this:
>
[quoted text clipped - 5 lines]
> }
> }
I prefer:
using (StreamWriter writer = File.CreateText("info.txt"),
string message = "Hello world.")
{
}
There are some contexts in which nesting using statements may make more
sense, but assuming the variables are nominally scoped to the same block
logically, the above syntax is preferable to me.
Pete
>Is a finalizer really a backup to Dispose? I've never heard that before
>and question how it could be used that way. I mean, you have no idea
>when a finalizer will be called so what can it do of any use since it
>will not know the state of any unmanaged resources by the time the
>finalizer runs? I don't think I've ever written a finalizer, especially
>not one that has anything to do with the IDispose pattern.
Yes, a finalizer is very commonly used as a backup of Dispose.
Actually the recommended implementation for Dispose is to create a
virtual protected member Dispose(bool disposing) and call that with
True if called from Dispose and False if called from the Finalizer.
The finalizer version of Dispose(false) is only useful when a class
contains unmanaged resources which have to be freed. Code paths
originating from a finalizer can not call managed objects because the
GC may collect them out of order (and their own finalizers should take
care of their own cleanup anyways).
HTH,
Sam
------------------------------------------------------------
We're hiring! B-Line Medical is seeking .NET
Developers for exciting positions in medical product
development in MD/DC. Work with a variety of technologies
in a relaxed team environment. See ads on Dice.com.
GlennDoten - 16 Aug 2007 14:25 GMT
>> Is a finalizer really a backup to Dispose? I've never heard that before
>> and question how it could be used that way. I mean, you have no idea
[quoted text clipped - 15 lines]
>
> HTH,
Thanks, Sam. It does help. I have a number of classes that implement the
dispose pattern, and use GC.SuppressFinalizer and all that, just had a
Senior's Moment, I guess.

Signature
-glenn-