Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

using (object) a Mystery for me!!!

0 views
Skip to first unread message

Duggi

unread,
Sep 9, 2008, 1:47:26 PM9/9/08
to
I used to wonder why MS implemented C# to accept the following code

using (Font f = new Font())
{
// some code here.
}

While the same can be achieved through

{
Font f = new Font()
// some code here.
}

Just making code as a block and create the object inside the block.
Why MS took pain to implement the semantics to understand in C# it as
in first block.

As per my understanding the above code does the following things
1. Creates a block where f is used
2. When code block completes execution, f is garbage collected.

I was wrong. There is one major significant difference between the two
code blocks.

Actually, what ever the object used in the using(object) statement,
has to implement IDisposable. I think by now you got the difference.
The beauty of the using(object) statement is that after the execution
of the using block object.Dispose() will be called by the framework,
releasing all the unmanaged resources.

See below code:

class TestC : IDisposable
{
public void UseLimitedResource()
{
Console.WriteLine("Using limited resource...");
}

void IDisposable.Dispose()
{
// this class uses significant unmanaged resources and are relesed
here.
Console.WriteLine("Disposing limited resource.");
}
}


class Program
{
static void Main(string[] args)
{
using (TestC testC = new TestC())
{
testC.UseLimitedResource();
}

Console.ReadLine();
}
}

However I ran into another BIG doubt that why C# allows the following
code

class Program
{
static void Main(string[] args)
{
TestC testC = new TestC()
using (testC)
{
testC.UseLimitedResource();
}

testC.UseLimitedResource();

Console.ReadLine();
}
}

Object is already disposed, still you can use it, driving to CRASHing
your own applications????

I appriciate your help understanding it properly.

-Cnu

Peter Duniho

unread,
Sep 9, 2008, 2:18:24 PM9/9/08
to
On Tue, 09 Sep 2008 10:47:26 -0700, Duggi <DuggiSri...@gmail.com>
wrote:

> [...]


> However I ran into another BIG doubt that why C# allows the following
> code
>
> class Program
> {
> static void Main(string[] args)
> {
> TestC testC = new TestC()
> using (testC)
> {
> testC.UseLimitedResource();
> }
>
> testC.UseLimitedResource();
>
> Console.ReadLine();
> }
> }
>
> Object is already disposed, still you can use it, driving to CRASHing
> your own applications????

Yes. The rule is don't try to use an object after it's been disposed.
The only exception is when the object itself clearly documents that it's
safe to use after disposal (rare, but not unheard of).

The code you posted violates the rule. It's no different than violating
any number of other rules in your code that lead to bugs when broken (for
example, trying to dereference a reference type when the variable has been
set to null...also allowed, but certainly not valid to do).

There are several reasons why C# can't prohibit the code example above,
but the exception described above is an important one. Such classes do
exist, and if the compiler prohibited the code you posted, it would block
otherwise legitimate code from working.

Pete

Ignacio Machin ( .NET/ C# MVP )

unread,
Sep 9, 2008, 4:19:06 PM9/9/08
to
On Sep 9, 1:47 pm, Duggi <DuggiSrinivasa...@gmail.com> wrote:
> I used to wonder why MS implemented C# to accept the following code
>
> using (Font f = new Font())
> {
>       // some code here.
>
> }
>
> While the same can be achieved through
>
> {
> Font f = new Font()
>       // some code here.
>
> }

It's nt the same, in the first you are explicitely telling the
compiler to Dispose the instance. If the type you place in the using
does not implement IDisposable yuo get an error:
using (Assembly a = Assembly.GetExecutingAssembly()){
}
You will get an error.

When you declare yuor instance INSDE the block, it simply is marked as
being disposable (if nobody hold a reference to it of course) but the
compile WILL NOT GENERATE code to dispose the instance.

> class Program
> {
> static void Main(string[] args)
>       {
> TestC testC = new TestC()
>             using (testC)
>             {
>                 testC.UseLimitedResource();
>             }
>
> testC.UseLimitedResource();
>
>             Console.ReadLine();
>        }
>
> }
>
> Object is already disposed, still you can use it, driving to CRASHing
> your own applications????

Not really, the object is marked as being disposable, it's not until
the GC runs that the object is REALLY disposed. Do a search for
WeakReference .
Besides your code is clearly a bad code, the compiler cannot prevent
htat kind of code from being written.

Jon Skeet [C# MVP]

unread,
Sep 9, 2008, 4:31:46 PM9/9/08
to
Ignacio Machin ( .NET/ C# MVP ) <ignacio...@gmail.com> wrote:
> > Object is already disposed, still you can use it, driving to CRASHing
> > your own applications????
>
> Not really, the object is marked as being disposable, it's not until
> the GC runs that the object is REALLY disposed. Do a search for
> WeakReference .
> Besides your code is clearly a bad code, the compiler cannot prevent
> htat kind of code from being written.

No, it's not "marked as disposable" - it *is* disposed, which is very
different from being garbage collected or finalized.

--
Jon Skeet - <sk...@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com

raylopez99

unread,
Sep 9, 2008, 6:05:15 PM9/9/08
to
On Sep 9, 1:31 pm, Jon Skeet [C# MVP] <sk...@pobox.com> wrote:

> Ignacio Machin ( .NET/ C# MVP ) <ignacio.mac...@gmail.com> wrote:

>
> No, it's not "marked as disposable" - it *is* disposed, which is very
> different from being garbage collected or finalized.
>

Whoa! Two MVPs disagreeing! Dangerous! Step back I see a brawl
a'comin'! :-)

My newbie answer to the OP is that points 1 and 2 of the OP are sound,
since 'using' is the same as:


'using (X) { //} is equivalent to (pseudo-code):

try { //} finally { if (X.Dispose();}

So 'using' is safer, since you can try a null pointer and it will not
crash your program, it will just trigger the catch or finally block.

RL

Göran Andersson

unread,
Sep 9, 2008, 7:27:33 PM9/9/08
to
Duggi wrote:
> Object is already disposed, still you can use it, driving to CRASHing
> your own applications????

The Dispose method is just a method like any other, there is nothing
magical about it that would make it impossible to use the object after
it's called.

Most objects are not very useful once you called Dispose, but that's
because of the code that was put in the Dispose method, not because of
the call in and of itself.

--
Göran Andersson
_____
http://www.guffa.com

Duggi

unread,
Sep 10, 2008, 1:03:50 PM9/10/08
to
On Sep 9, 1:31 pm, Jon Skeet [C# MVP] <sk...@pobox.com> wrote:

Agreed. I think objects that are marked for finalization are garbage
collected when garbage collector is ran, However dispose will be
called then and there itself.

-Cnu

Jon Skeet [C# MVP]

unread,
Sep 10, 2008, 1:14:10 PM9/10/08
to
Duggi <DuggiSri...@gmail.com> wrote:
> On Sep 9, 1:31 pm, Jon Skeet [C# MVP] <sk...@pobox.com> wrote:
> > Ignacio Machin ( .NET/ C# MVP ) <ignacio.mac...@gmail.com> wrote:
> >
> > > > Object is already disposed, still you can use it, driving to CRASHing
> > > > your own applications????
> >
> > > Not really, the object is marked as being disposable, it's not until
> > > the GC runs that the object is REALLY disposed. Do a search for
> > > WeakReference .
> > > Besides your code is clearly a bad code, the compiler cannot prevent
> > > htat kind of code from being written.
> >
> > No, it's not "marked as disposable" - it *is* disposed, which is very
> > different from being garbage collected or finalized.
>
> Agreed. I think objects that are marked for finalization are garbage
> collected when garbage collector is ran, However dispose will be
> called then and there itself.

Only if the finalizer is written to call Dispose. Finalization doesn't
*automatically* call Dispose. As far as the runtime is concerned,
IDisposable is just another interface and Dispose is just another
method.

Mythran

unread,
Sep 11, 2008, 7:34:10 PM9/11/08
to

"raylopez99" <raylo...@yahoo.com> wrote in message
news:e72943b5-2e85-4290...@j22g2000hsf.googlegroups.com...
... >SNIP<


> My newbie answer to the OP is that points 1 and 2 of the OP are sound,
> since 'using' is the same as:
>
>
> 'using (X) { //} is equivalent to (pseudo-code):
>
> try { //} finally { if (X.Dispose();}
>
> So 'using' is safer, since you can try a null pointer and it will not
> crash your program, it will just trigger the catch or finally block.
>
> RL

Close, but no...your pseudo-code is a little off or lacking a little.

using (X) {
// some code here
}

is similar to (but not 100% positive unless we reflect the IL):

// # Compilation check here to ensure X implements IDisposable.
try {
// some code here
} finally {
if (X != null) {
X.Dispose();
}
}

From my tests (again, I have not looked at the IL for this), there are a few
differences to my example than yours (besides the simple compilation errors
from the pseudo-code):

1.) There is a compilation check to make sure X implements IDisposable.
2.) In the finally block, there the code checks to see if X is NOT null.

A third thing that is similar for both, but doesn't really show unless you
see it or *understand* it is that you can declare and create an instance of
X for use ONLY in the using block, while you can't do the same thing in the
try...finally block.

Example:

using (MyClass X = new MyClass()) {
// some code here.
}

while you can't do:
try {
MyClass X = new MyClass();
// some code here.
} finally {
if (X != null) {
X.Dispose();
}
}

Hope this helps a bit more :)

Mythran

Peter Duniho

unread,
Sep 11, 2008, 10:23:09 PM9/11/08
to
On Thu, 11 Sep 2008 16:34:10 -0700, Mythran <Myt...@community.nospam>
wrote:

> [...]


> 1.) There is a compilation check to make sure X implements IDisposable.
> 2.) In the finally block, there the code checks to see if X is NOT null.
>
> A third thing that is similar for both, but doesn't really show unless
> you see it or *understand* it is that you can declare and create an
> instance of X for use ONLY in the using block, while you can't do the
> same thing in the try...finally block.

In addition to the three points you've made, it's also helpful to know
that when using the "using" statement, the target variable used in the
"using" statement is read-only. The compiler will emit an error if you
try to modify its value inside the "using" statement.

The C# specification has these details on the various specific
requirements of the implementation of "using".

Pete

0 new messages