using statement is not behaving?

J

Jeff Clement

I believe the using statement is not behaving as documented
on
http://msdn.microsoft.com/library/en-us/csspec/html/vclrfcsharpspec_8_13.asp
and in the ECMA specs. It sounds like using is simply a
wrapper around some code that calls Dispose on the resource
provided. In the documentation it says that:

using (ResourceType resource = expression) statement

Corresponds to:

{
ResourceType resource = expression;
try {
statement;
}
finally {
if (resource != null) ((IDisposable)resource).Dispose();
}
}

This implies that a using block will simply call Dispose on
the provided resource. It is not responsible for
supressing finalization or anything like that right?

I've written some test code that, I think, proves that the
above documentation is false. The using block is behaving
differently from the simple try finally block. Using does
call Dispose but is somehow preventing the object from
being GC'd.

using System;

namespace ConsoleApplication10
{
class TestClass:IDisposable
{
~TestClass()
{
System.Console.WriteLine("Finalized!");
}
#region IDisposable Members

public void Dispose()
{
System.Console.WriteLine("GC'd");
}

#endregion
}

class Class1
{
[STAThread]
static void Main(string[] args)
{
// Test #1 using a using statement
System.Console.WriteLine("Using Test: Should Call GC
then Finalizer but doesn't");
using (TestClass c1 = new TestClass()) {}
GC.Collect();

// Test #2 using a try/finally equiv to using statement
System.Console.WriteLine("Using Test: Should Call GC
then Finalizer but doesn't");
TestClass c2 = new TestClass();
try {}
finally {if (c2!=null) ((IDisposable)c2).Dispose();}
c2 = null;
GC.Collect();

System.Console.ReadLine();
}
}
}

The output of this program should be:

Using Test: Should Call GC then Finalizer but doesn't
GC'd
Finalized!
Using Test: Should Call GC then Finalizer
GC'd
Finalized!

But what is actually happening is:

Using Test: Should Call GC then Finalizer but doesn't
GC'd
Using Test: Should Call GC then Finalizer
GC'd
Finalized!

Notice the object is never finalized when using using but
it should be because it's dropped out of scope and I have
not suppressed GC for this object.

Can anyone confirm that this is a deviation from the
expected behaviour? I'm using .NET Framework 1.1.

Thanks,
Jeff
 
J

Jon Skeet [C# MVP]

Jeff Clement said:
I believe the using statement is not behaving as documented
on
http://msdn.microsoft.com/library/en-us/csspec/html/vclrfcsharpspec_8_13.asp
and in the ECMA specs. It sounds like using is simply a
wrapper around some code that calls Dispose on the resource
provided. In the documentation it says that:

using (ResourceType resource = expression) statement

Corresponds to:

{
ResourceType resource = expression;
try {
statement;
}
finally {
if (resource != null) ((IDisposable)resource).Dispose();
}
}

This implies that a using block will simply call Dispose on
the provided resource. It is not responsible for
supressing finalization or anything like that right?
No.

I've written some test code that, I think, proves that the
above documentation is false. The using block is behaving
differently from the simple try finally block. Using does
call Dispose but is somehow preventing the object from
being GC'd.

Not as far as I can see. The results of your program on my box are:

Using Test: Should Call GC then Finalizer but doesn't
GC'd
Finalized!
Using Test: Should Call GC then Finalizer but doesn't
GC'd
Finalized!

Note that your diagnostics are actually wrong, as Dispose being called
*doesn't* mean it's been garbage collected.

However, I *suspect* the real problem here is either that the debugger
is keeping things from being garbage collected until the end of the
method, or that you're not seeing the finalization until later due to
you not having put in a call to GC.WaitForPendingFinalizers.
 
D

Daniel Pratt

Hi Jeff,
I believe the using statement is not behaving as documented
on http://msdn.microsoft.com/library/en-us/csspec/html/vclrfcsharpspec_8_13.asp
and in the ECMA specs. It sounds like using is simply a
wrapper around some code that calls Dispose on the resource
provided.
Notice the object is never finalized when using using but
it should be because it's dropped out of scope and I have
not suppressed GC for this object.

Can anyone confirm that this is a deviation from the
expected behaviour? I'm using .NET Framework 1.1.

My understanding is that finalization is a two step process. That is,
the instance is marked for finalization in pass 1 and actually finalized in
pass 2. As such, I would guess that the output "Finalized!" is coming from
the instance pointed to by c1 not by c2. That would be easy enough to
confirm, of course.

Regards,
Daniel
 
J

Jeffrey Tan[MSFT]

Hi Jeff,

Based on my understanding, you have some problem about "using statement"

On my machine, it runs result as:

Using Test: Should Call GC then Finalizer but doesn't
GC'd
Using Test: Should Call GC then Finalizer
GC'd
Finalized!
Finalized!

Actually, The using statement defines a scope at the end of which an object
will be disposed.

As you can see that the TestClass.Dispose is really called when at the end
of using statement scope. So I think it behaves well.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
J

Jeffrey Tan[MSFT]

Hi Jeff,

Does the community's reply make sense to you?

Please feel free to feedback. Thanks

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 

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

Top