Once again on try/catch, using and IO

R

RayLopez99

Examine the below. It works, but my question is, since 'using' is
equivalent to 'try/catch', why do we need the outer try/catch block to
catch the situation where "MyFile.txt" does not exist?

RL

try
{

using (FileStream fs = File.OpenRead
("MyFile.txt")) //ASSUME "MyFile.txt" does not exist
{

using (TextReader reader = new StreamReader(fs))
{

StringBuilder myStringBuilderString = new
StringBuilder();
myStringBuilderString = new StringBuilder
(reader.ReadToEnd()); //read in entire string to end

}
}
}
catch (IOException Ex)
{
MessageBox.Show("Error: could not read file: " +
Ex.Message);
}
 
A

Arne Vajhøj

RayLopez99 said:
Examine the below. It works, but my question is, since 'using' is
equivalent to 'try/catch',

It is not. It is a try finally.
why do we need the outer try/catch block to
catch the situation where "MyFile.txt" does not exist?
try
{

using (FileStream fs = File.OpenRead("MyFile.txt")) //ASSUME "MyFile.txt" does not exist
{
using (TextReader reader = new StreamReader(fs))
{
}
}
}
catch (IOException Ex)
{
MessageBox.Show("Error: could not read file: " + Ex.Message);
}

You use the catch to inform about the exception.

Arne
 
S

Stephany Young

NO ... 'using' is not equivalent to 'try/catch', it is the equivalent of
'instantiate .... dispose'.

What you have is the equivalent of:

try
{
FileStream fs = File.OpenRead("MyFile.txt"); //ASSUME "MyFile.txt" does
not exist
TextReader reader = new StreamReader(fs);
StringBuilder myStringBuilderString = new StringBuilder();
myStringBuilderString = new StringBuilder(reader.ReadToEnd()); //read in
entire string to end
reader.Dispose();
fs.Dispose();
}
catch (IOException Ex)
{
MessageBox.Show("Error: could not read file: " + Ex.Message);
}

The problem with this is that, if the exception is thrown, the FileStream
and TextReader objects will NOT be disposed of by the try/catch construct.

The 'using' construct ensures that the FileStream and TextReader will be
disposed of regardless of whether or not an exception was thrown.

But, the point is, if you want to catch an exception then you still need to
use the 'try/catch' construct.

FYI, the:

StringBuilder myStringBuilderString = new StringBuilder();
myStringBuilderString = new StringBuilder(reader.ReadToEnd()); //read in
entire string to end

is a bit redundant:

StringBuilder myStringBuilderString = new
StringBuilder(reader.ReadToEnd()); //read in entire string to end

will do the trick.
 
G

Göran Andersson

Stephany said:
NO ... 'using' is not equivalent to 'try/catch', it is the equivalent of
'instantiate .... dispose'.

What you have is the equivalent of:

Not quite, there are some try...finally there also:
try
{
FileStream fs = File.OpenRead("MyFile.txt"); //ASSUME "MyFile.txt"
does not exist try {
TextReader reader = new StreamReader(fs); try {
StringBuilder myStringBuilderString = new StringBuilder();
myStringBuilderString = new StringBuilder(reader.ReadToEnd()); //read
in entire string to end } finally {
reader.Dispose();
}
} finally {
fs.Dispose(); }
}
catch (IOException Ex)
{
MessageBox.Show("Error: could not read file: " + Ex.Message);
}

The problem with this is that, if the exception is thrown, the
FileStream and TextReader objects will NOT be disposed of by the
try/catch construct.

The 'using' construct ensures that the FileStream and TextReader will be
disposed of regardless of whether or not an exception was thrown.

But, the point is, if you want to catch an exception then you still need
to use the 'try/catch' construct.

FYI, the:

StringBuilder myStringBuilderString = new StringBuilder();
myStringBuilderString = new StringBuilder(reader.ReadToEnd()); //read
in entire string to end

is a bit redundant:

StringBuilder myStringBuilderString = new
StringBuilder(reader.ReadToEnd()); //read in entire string to end

will do the trick.

Well, the use of a StringBuilder at all in this case seems redundant to
mee...
 
S

Stephany Young

Well, yes ... it is painfully obvious that one could use a 'try/finally'
instead of a 'using', but a only if one declares the objects of interest
outside the 'try/finally' block and also 'disposes' of the objects of
interest in the 'finally' section.

The whole point of a 'using' is that the object of interest is both
declared, instatntated and disposed of within the 'using' block.

BUT ... If you re-read the OP you will see that the poster was expecting the
'using' to catch the exception.
 
M

Michael C

Stephany Young said:
Well, yes ... it is painfully obvious that one could use a 'try/finally'
instead of a 'using', but a only if one declares the objects of interest
outside the 'try/finally' block and also 'disposes' of the objects of
interest in the 'finally' section.

Of course, you're not going to create the object after the try because then
if it doesn't get created you'll try to dispose something that doesn't exist
:)
The whole point of a 'using' is that the object of interest is both
declared, instatntated and disposed of within the 'using' block.

BUT ... If you re-read the OP you will see that the poster was expecting
the 'using' to catch the exception.
 
G

Göran Andersson

Stephany said:
Well, yes ... it is painfully obvious that one could use a 'try/finally'
instead of a 'using', but a only if one declares the objects of interest
outside the 'try/finally' block and also 'disposes' of the objects of
interest in the 'finally' section.

Yes, that is exactly what the using statement does.
The whole point of a 'using' is that the object of interest is both
declared, instatntated and disposed of within the 'using' block.

No, it isn't.
 
R

RayLopez99

According to whom?

The "using" statement doesn't require the object be declared or  
instantiated within the "using" block (including the statement itself), so  
it seems obvious that your statement can't be true.

It _is_ correct that "using" doesn't "catch" an exception.  You and Göran  
have both correctly pointed out that "using" is not equivalent to  
"try/catch" because there's no "catch" in what a "using" statement  
provides.

Göran's paraphrasing of the "using" statement is nearly correct, only with  
the caveat that a) it actually checks for null before trying to dispose,  
b) the allocation is actually done outside of the try/finally, and c) it  
adds the semantics that the variable holding the reference is effectively 
made read-only (you can't modify it inside the "using" block).

Pete

Well this is starting to get confusing for little me. I guess
Go<umlaut>ran is saying essentially that 'using' is equivalent to try/
finally (not try/catch as I erroneously posted in the OP).

Here is something else along these lines I found on the net...(see
below).

RL

Anti-pattern: incorrect try..finally usage

I am so sick of seeing this incorrect usage of try..finally:

Stream s = null;
try {
s = new FileStream(...);
...
}
finally {
if(s!=null) s.Close();
}

This is WRONG. The work done in the finally block need only be done if
the stream is opened. Until the assignment of 's' completes, the
finally block is not to be executed. The 'if' statement is basically
checking that fact. The correct usage is:

Stream s = new FileStream(...);
//A
try {
...
}
finally {
s.Close();
} //B

No excuses!

RL: I think this last part, from //A to //B, can be replaced by:
using (s) { }, but I'm not sure on the format...
 

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

Similar Threads


Top