Proper use of the "using" statement

  • Thread starter Thread starter Andreas =?ISO-8859-1?Q?M=FCller?=
  • Start date Start date
A

Andreas =?ISO-8859-1?Q?M=FCller?=

Hi all,

I have a class SwitchCursor, that implements IDisposable. Is it legal
to use an object that is not assigned to a reference inside a using
statement like this:

using(new SwitchCursor())// is the SwitchCursor safe from GC?
{
}

or is the Object eligible for GC?

Thanks in advance,
Andy
 
Andreas Müller said:
I have a class SwitchCursor, that implements IDisposable. Is it legal
to use an object that is not assigned to a reference inside a using
statement like this:

using(new SwitchCursor())// is the SwitchCursor safe from GC?
{
}

or is the Object eligible for GC?

You can't do that, as the syntax for the using construct requires that
you assign the value to a variable.
 
Jon,

Actually, you can do that. According to section 8.13 (The using
statement) of the C# spec, the using keyword only requires a valid
expression or a local variable declaration. I think that the C#
programmer's reference is incorrect.

The following code:

using (new System.Data.DataSet())
{
}

will compile. It also creates an implicit variable declaration which it
is stored in. This will keep it from being GCed until the using block
exits.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Andreas Müller said:
I have a class SwitchCursor, that implements IDisposable. Is it legal
to use an object that is not assigned to a reference inside a using
statement like this:

using(new SwitchCursor())// is the SwitchCursor safe from GC?
{
}

or is the Object eligible for GC?

You can't do that, as the syntax for the using construct requires that
you assign the value to a variable.
 
Nicholas Paldino said:
Actually, you can do that. According to section 8.13 (The using
statement) of the C# spec, the using keyword only requires a valid
expression or a local variable declaration. I think that the C#
programmer's reference is incorrect.

The following code:

using (new System.Data.DataSet())
{
}

will compile. It also creates an implicit variable declaration which it
is stored in. This will keep it from being GCed until the using block
exits.

Ah - I was misreading the ECMA spec. Doh :(
 
How would that be used? I mean if you can't access that dataset since you
don't know the implicit variable name what is the purpose of creating it?
 
Daniel Billingsley said:
How would that be used? I mean if you can't access that dataset since you
don't know the implicit variable name what is the purpose of creating it?

It could be used for locking purposes, or possibly tracing purposes.
For instance:

using (new TraceBlock ("doing something"))
{
...
}

where TraceBlock would have a static thread-local stack of "names" in
it, which could be dumped if you wanted. Creating a new TrackBlock
would add the name to the stack, and disposing it would pop the top
element.

That's just an example off the top of my head, and it's not terribly
good. I'm sure it's quite rare, but there are probably a few real cases
around :)
 
It could be used for locking purposes, or possibly tracing purposes.
For instance:

Another possible use might be with a product such as Raize CodeSite, in
which you could scope tracing. The constructor would then log the entry
into the scope, and the destructor/finalize method would log the exit out
of the scope. This could provide timing information as well as provide you
with a stack-trace like log for evidence gathering for a particularly
hard-to-find problem. Just a thought anyway.

(To Jon: Sorry about the email, I tried the "Quick Reply" of Opera and it
used email reply in a newsgroup)
 
[Please do not mail me a copy of your followup]

Jon Skeet [C# MVP] <[email protected]> spake the secret code
That's just an example off the top of my head, and it's not terribly
good. I'm sure it's quite rare, but there are probably a few real cases
around :)

There are lots of examples where anonymous items in a using statement
are useful. Basically, any time you have to do something like this:

try
{
StartSomething();
// do stuff
}
finally
{
EndSomething();
}

You can encapsulate the Start/End inside an IDisposable class. An
extremely simple example is a helper class that puts up a wait cursor
around a potentially long operation:

public class CursorWaiter : IDisposable
{
public CursorWaiter()
{
Cursor.Current = Cursors.WaitCursor;
}
~CursorWaiter()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
}
protected void Dispose(bool disposing)
{
if (disposing)
{
GC.SuppressFinalize(this);
Cursor.Current = Cursors.Default;
}
}
}

// ...
using (new CursorWaiter())
{
// do slow stuff
}

You don't need a name for the CursorWaiter() instance because you
don't need to access it within the enclosed scope.
 
So, doing something like...

using (new CursorWaiter())
{
try
{}
catch
{}
}

right?

In this "extremely simple" example that doesn't really provide any
tremendous advantage over just changing the cursor in the try and finally
blocks, does it? I realize it could be more beneficial if that helper class
did more - I'm just trying to make sure I'm not missing something here.

Rich said:
[Please do not mail me a copy of your followup]

Jon Skeet [C# MVP] <[email protected]> spake the secret code
That's just an example off the top of my head, and it's not terribly
good. I'm sure it's quite rare, but there are probably a few real cases
around :)

There are lots of examples where anonymous items in a using statement
are useful. Basically, any time you have to do something like this:

try
{
StartSomething();
// do stuff
}
finally
{
EndSomething();
}

You can encapsulate the Start/End inside an IDisposable class. An
extremely simple example is a helper class that puts up a wait cursor
around a potentially long operation:

public class CursorWaiter : IDisposable
{
public CursorWaiter()
{
Cursor.Current = Cursors.WaitCursor;
}
~CursorWaiter()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
}
protected void Dispose(bool disposing)
{
if (disposing)
{
GC.SuppressFinalize(this);
Cursor.Current = Cursors.Default;
}
}
}

// ...
using (new CursorWaiter())
{
// do slow stuff
}

You don't need a name for the CursorWaiter() instance because you
don't need to access it within the enclosed scope.
--
"The Direct3D Graphics Pipeline"-- code samples, sample chapter, FAQ:
<http://www.xmission.com/~legalize/book/>
Pilgrimage: Utah's annual demoparty
<http://pilgrimage.scene.org>
 
[Please do not mail me a copy of your followup]

"Daniel Billingsley" <[email protected]> spake the secret code
So, doing something like...

using (new CursorWaiter())
{
try
{}
catch
{}
}

right?

Nope. The whole point of putting it in the using clause is that the
cursor will be restored no matter how you exit the enclosed block: a
shortcut return statement, an exception, or normal execution flow
through the last statement.
In this "extremely simple" example that doesn't really provide any
tremendous advantage over just changing the cursor in the try and finally
blocks, does it?

Yes, it does. You don't have to write the try/finally blocks if you
use the using statement, assuming that the only reason you wrote
try/finally in the first place was to restore the cursor when you
exited the "slow processing" step.
 
Back
Top