Disposables, Using & Try/Catch Blocks
Having a mental block today, need a hand verifying my logic isn't fubar'ed.
Traditionally I would do file i/o similar to this:
FileStream fs = null; // So it's visible in the finally block
try
{
fs = File.Open("Foo.txt", FileMode.Open);
/// Do Stuff
}
catch(IOException)
{
/// Handle Stuff
}
finally
{
if (fs != null)
fs.Close();
}
However, this isn't very elegant.
Ideally I'd like to use the using
block to dispose of the filestream when I'm done, however I am unsure about the synergy between using and try/catch.
This is how i'd like to implement the above:
try
{
using(FileStream fs = File.Open("Foo.txt", FileMode.Open))
{
/// Do Stuff
}
}
catch(Exception)
{
/// Handle Stuff
}
However, I'm worried that a premature exit (via thrown exception) from within the using block may not allow the using block to complete execution and clean up it's object. Am I开发者_Go百科 just paranoid, or will this actually work the way I intend it to?
You're just being paranoid and it will work the way you intend it to :)
A using statement is equivalent to a try/finally block, whether it's inside a try/catch or not.
So your code is similar to:
try
{
FileStream fs = null;
try
{
fs = File.Open("Foo.txt", FileMode.Open);
// Do stuff
}
finally
{
if (fs != null)
{
fs.Dispose();
}
}
}
catch(Exception)
{
/// Handle Stuff
}
Don't worry, it will clean up as expected and is cleaner than your original.
In fact it's much more common to have a try/finally aka using statement in your business logic, and a try/catch in a top-level handler in the UI tier or at a physical tier boundary. Something like:
try
{
DoStuffWithFile("foo.txt");
}
catch(Exception ex)
{
...
}
and
public void DoStuffWithFile(string fileName)
{
using(FileStream fs = File.Open(fileName,...))
{
// Do Stuff
}
}
This will work - internally the using statement compiles the same way as a try-finally block
try
{
FileStream fs = null;
try
{
fs = File.Open("Foo.txt", FileMode.Open);
}
finally
{
fs.Dispose();
}
}
catch(Exception)
{
/// Handle Stuff
}
second piece of code gets translated into this
The using block will work exactly as you entend translated the using block is really just
try
{
FileStream fs = null;
try
{
fs = File.Open("Foo.txt", FileMode.Open))
//Do Stuff
}
finally
{
if(fs != null)
fs.Dispose();
}
}
catch(Exception)
{
/// Handle Stuff
}
You don't need the try..finally
if you have a using()
. They perform the same operation.
If you're not convinced, point Reflector at your assembly and compare the generated code.
精彩评论