Finally vs Using

  • Thread starter Thread starter Fred Chateau
  • Start date Start date
F

Fred Chateau

What are the differences between a "finally" and a "using" block?

Is it still necessary (or advisable) to use "try" and "catch" blocks within
a "using" block?
 
I believe they have no relation to each other.

"finally" is used to ensure that code gets executed regardless of whether an
exception occurred or not in a try/catch block. A using statement is just a
shortcut for way of initializing variables that rely on the Dispose method.
When the "using" block finishes, the system will automatically call the
Dispose method on the object.

Your use of each construct is independent of the use of the other one.
 
Hi,
you can test a example like this:
the block it may throw a exception to client,when you use using,it may not
handle it and release related resources.but try/catch/finally will handle
and release revant resource success.try it yourself may can understand it .

--
---------ÌÕ×æºé(Ñ©ÔÆÓ¥)------------
MSN:xueyunying@hotmailcom
http://shanquan.blogone.net
Mail:[email protected]
·ÖÏí֪ʶ£¬¹²´´¼¤Ç飬¹²Í¬³É¾Í
Share Knowledge,Share Vision,Share
Success
 
using (MyResource res = new MyResource())
{
DoSomething(res);
}

if strictly equivalent to:

{
MyResource res = new MyResource();
try
{
DoSomething(res);
}
finally
{
res.Dispose();
}
}

So, my advice is to use the first form rather than the second one. If you do
this, there should be little use for finally, because most of the situations
where you need a finally block should be related to resource disposal and
coded with "using" rather than finally.

Bruno.
 
Hi Fred,

Thanks for posting in this group.
I think Peter's post has tell the main purpose and difference of Finally
and Using.
You still should use "try" and "catch" blocks to handle the exceptions in
your program.
For more details, please refer to the MSDN document:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpconusingfinallyblock.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csspec/html
/vclrfcsharpspec_8_13.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpconusingtrycatchblocktocatchexceptions.asp

Hope this helps,

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.
 
Peter Rilling said:
I believe they have no relation to each other.

Yes they do. In particular, the C# language specification says that:

<quote>
A using statement of the form

using (R r1 = new R()) {
r1.F();
}

is precisely equivalent to

R r1 = new R();
try {
r1.F();
}
finally {
if (r1 != null) ((IDisposable)r1).Dispose();
}
</quote>

You can certainly use each construct within the other, but they're not
unrelated. "using" is just a quick way of doing a try/finally pair of
blocks.
 
Ñ©ÔÆÓ¥ said:
you can test a example like this:
the block it may throw a exception to client,when you use using,it may not
handle it and release related resources.

Yes it will, because that's the whole point of the "using" construct -
it acts as an elegant way of writing a try/finally pair.
 
Hi Jon,

You 're right but the code given by the C# specs is a bit misleading:

* The "if (r1 != null)" test is useless because r1 is never null (if "new
R()" fails, it throws an exception but does not return null).

* The try/finally version lacks curly braces around the whole block, to get
the same scoping as the "using" statement on the r1 variable.

Bruno.
 
Bruno Jouhier said:
You 're right but the code given by the C# specs is a bit misleading:

* The "if (r1 != null)" test is useless because r1 is never null (if "new
R()" fails, it throws an exception but does not return null).

Indeed. On the other hand, a different way of acquiring the resource
*may* return null instead of throwing an exception, in which case no
call to Dispose is made. For instance:

using System;

public class Test : IDisposable
{
static void Main()
{
using (Test t = new Test())
{
Console.WriteLine ("Got one");
}

using (Test t = GiveMeNull())
{
Console.WriteLine ("Not got one");
}
}

static Test GiveMeNull()
{
return null;
}

public void Dispose()
{
Console.WriteLine ("Disposing");
}
}

It would have been better if the example code in the language
specification had included an example of acquiring resources other than
with a constructor.
* The try/finally version lacks curly braces around the whole block, to get
the same scoping as the "using" statement on the r1 variable.

True. This appears to be an actual bug in the spec.
 
I believe they have no relation to each other.
i believe he was talking about
using(x)
{
}
in which case there is a relation.
 
""Jeffrey Tan[MSFT]"" wrote...
I think Peter's post has tell the main purpose and difference of Finally and Using.
You still should use "try" and "catch" blocks to handle the exceptions in
your program.

Well, at least after reading this thread, I don't feel so stupid about
asking the question. It appears a little more complicated than I first
thought. :)

It sounds like working with "try" and "catch" blocks inside a "using"
statement might be a good way to code. Is it safe to assume that in all
Framework classes, Dispose will always call Close (if it exists) on a
resource before releasing it?

Also, on a related subject, I was reading the documentation today on the
System.Data.ODBC namespace and I noticed in the example of OdbcDataReader
that it says "always call Close when done reading". Aside from the poor
English, this can be confusing. :)

Is there a easy way to determine whether a resource "must" be closed
explicitly (as opposed to preferably)? Maybe the documentation should read:

// ... always call Close when done reading.
// Close the connection when done with it ... (This time we really, really
mean it!) ;)

Is there a simple way to determine which resources actually tie up native
resources and "must" be freed before going out of scope, short of sifting
through pages and pages of documentation? At first I thought maybe just
checking to see if a resource implements IDisposable would work, but I
notice DataReaders also implement that interface, so I guess it's not a good
indicator of what's really happening.

Thank you all for your help . . .
 
One subtle difference between these two is, when using the finally block,
doing a Close/Dispose on a resource could throw an exception, while using
"using" will take care of the exception by itself.

One example to prove this is to open a File Stream to write to a floppy disk
and write more than the disk can hold. Since doing a close on the file
stream will flush the stream, it will throw an exception. So, now, there's
no way to get rid of the file stream. But when you use "using", the
internal file handle is closed properly (how?? I don't know).

-vJ
 
Fred Chateau said:
Also, on a related subject, I was reading the documentation today on the
System.Data.ODBC namespace and I noticed in the example of OdbcDataReader
that it says "always call Close when done reading". Aside from the poor
English, this can be confusing. :)

I believe Close will just call Dispose anyway - that would be the
conventional behaviour, certainly, although I believe it should be
explicitly documented.
Is there a easy way to determine whether a resource "must" be closed
explicitly (as opposed to preferably)? Maybe the documentation should read:

// ... always call Close when done reading.
// Close the connection when done with it ... (This time we really, really
mean it!) ;)

Is there a simple way to determine which resources actually tie up native
resources and "must" be freed before going out of scope, short of sifting
through pages and pages of documentation? At first I thought maybe just
checking to see if a resource implements IDisposable would work, but I
notice DataReaders also implement that interface, so I guess it's not a good
indicator of what's really happening.

Seeing whether or not it implements IDisposable *is* the right way to
find out, IMO - just call Dispose (usually with a using statement) on
everything which implements it.
 
In general the null check is not useless because the body of the using
statement is free to assign to r1 at any time. However, the null tests will
not occur in the translation (and neither will the cast) if R is a struct.
HTH
Cheers
Jon Jagger


Bruno Jouhier said:
Hi Jon,

You 're right but the code given by the C# specs is a bit misleading:

* The "if (r1 != null)" test is useless because r1 is never null (if "new
R()" fails, it throws an exception but does not return null).

* The try/finally version lacks curly braces around the whole block, to get
the same scoping as the "using" statement on the r1 variable.

Bruno.
 
Jon Jagger said:
In general the null check is not useless because the body of the using
statement is free to assign to r1 at any time.

No it's not - the local variable is read-only.
 
Hi Fred,

I think Jon's post has answnered your question.
Do you still have any concern?
Please feel free to let me know.

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.
 
Back
Top