I know how to use try-catch-finally. However I do not get the advance of using finally as I always can place the code after the try-catch block.
Is there any clear example?
Where the finally is necessary?
933 views Asked by Tray13 AtThere are 11 answers
On
try
{
DoSomethingImportant();
}
finally
{
ItIsRidiculouslyImportantThatThisRuns();
}
When you have a finally block, the code therein is guaranteed to run upon exit of the try. If you place code outside of the try/catch, that is not the case. A more common example is the one utilized with disposable resources when you use the using statement.
using (StreamReader reader = new StreamReader(filename))
{
}
expands to
StreamReader reader = null;
try
{
reader = new StreamReader(filename);
// do work
}
finally
{
if (reader != null)
((IDisposable)reader).Dispose();
}
This ensures that all unmanaged resources get disposed and released, even in the case of an exception during the try.
*Note that there are situations when control does not exit the try, and the finally would not actually run. As an easy example, PowerFailureException.
On
You need a finally because you should not always have a catch:
void M()
{
var fs = new FileStream(...);
try
{
fs.Write(...);
}
finally
{
fs.Close();
}
}
The above method does not catch errors from using fs, leaving them to the caller. But it should always close the stream.
Note that this kind of code would normally use a using() {} block but that is just shorthand for a try/finally. To be complete:
using(var fs = new FileStream(...))
{
fs.Write(...);
} // invisible finally here
On
It's almost always used for cleanup, usually implicitly via a using statement:
FileStream stream = new FileStream(...);
try
{
// Read some stuff
}
finally
{
stream.Dispose();
}
Now this is not equivalent to
FileStream stream = new FileStream(...);
// Read some stuff
stream.Dispose();
because the "read some stuff" code could throw an exception or possibly return - and however it completes, we want to dispose of the stream.
So finally blocks are usually for resource cleanup of some kind. However, in C# they're usually implicit via a using statement:
using (FileStream stream = new FileStream(...))
{
// Read some stuff
} // Dispose called automatically
finally blocks are much more common in Java than in C#, precisely because of the using statement. I very rarely write my own finally blocks in C#.
On
The code put in the finally block is executed even when:
- there are
returnstatements in thetryorcatchblock
OR - the
catchblock rethrows the exception
Example:
public int Foo()
{
try
{
MethodThatCausesException();
}
catch
{
return 0;
}
// this will NOT be executed
ReleaseResources();
}
public int Bar()
{
try
{
MethodThatCausesException();
}
catch
{
return 0;
}
finally
{
// this will be executed
ReleaseResources();
}
}
On
If an exception occurs (or is rethrown) in the catch-block, the code after the catch won't be executed - in contrast, code inside a finally will still be executed.
In addition, code inside a finally is even executed when the method is exited using return.
Finally is especially handy when dealing with external resources like files which need to be closed:
Stream file;
try
{
file = File.Open(/**/);
//...
if (someCondition)
return;
//...
}
catch (Exception ex)
{
//Notify the user
}
finally
{
if (file != null)
file.Close();
}
Note however, that in this example you could also use using:
using (Stream file = File.Open(/**/))
{
//Code
}
Update: This is actually not a great answer. On the other hand, maybe it is a good answer because it illustrates a perfect example of
finallysucceeding where a developer (i.e., me) might fail to ensure cleanup properly. In the below code, consider the scenario where an exception other thanSpecificExceptionis thrown. Then the first example will still perform cleanup, while the second will not, even though the developer may think "I caught the exception and handled it, so surely the subsequent code will run."Everybody's giving reasons to use
try/finallywithout acatch. It can still make sense to do so with acatch, even if you're throwing an exception. Consider the case* where you want to return a value.The alternative to the above without a
finallyis (in my opinion) somewhat less readable:*I do think a better example of
try/catch/finallyis when the exception is re-thrown (usingthrow, notthrow ex—but that's another topic) in thecatchblock, and so thefinallyis necessary as without it code after thetry/catchwould not run. This is typically accomplished with ausingstatement on anIDisposableresource, but that's not always the case. Sometimes the cleanup is not specifically aDisposecall (or is more than just aDisposecall).