I'm wondering if this code will work in the way that after 10 retries CleanUp() will be called? Or will the throw new Exception() not get caught by the last catch block?
public void Process()
{
try
{}
catch (MyException e)
{
int retries = GetRetries();
if(retries > 10)
{
_logger.LogError("Retried event already {retries} times. Giving up.", retries);
throw new Exception("Giving up!");
}
Process();
}
catch (Exception e)
{
CleanUp();
}
}
No, it doesn't work like that. For any given try/catch block, only an exception originating in the try can be caught by the corresponding catch blocks. Exceptions thrown within catch blocks are not catchable by other catch blocks at the same level.
finally blocks allow you to run code when control leaves a try/catch for any reason. So if the end of your try already has a CleanUp then you would just change your final catch(Exception e) to finally and remove the CleanUp at the end of the try part.
If, however, you only want to run CleanUp when control leaves the try/catch via an exception, you're not so lucky. There is a fault clause in IL, which is finally, but only for exceptions, but that's not exposed in C#.
So if you need that, it's usually best to introduce an extra bool that indicates you reached the end of the try block without exception, and use that to make your CleanUp call conditional in the finally.
Or you may simulate try/catch/fault by nesting try/catch blocks:
try
{
try
{}
catch (MyException e)
{
int retries = GetRetries();
if(retries > 10)
{
_logger.LogError("Retried event already {retries} times. Giving up.", retries);
throw new Exception("Giving up!");
}
Process();
}
}
catch
{
//Act as fault
CleanUp();
throw;
}
Related
Ok, as far as I understand, try/catch blocks try an operation and catch blocks catch exceptions. The more specific exceptions go up top, the more generic towards the bottom of the series of catch blocks. In the following code, I implement try/catch, everything works fine.
As far as I understand, a finally block always executes. Some people have argued that there is no purpose to finally block, because if there is an exception or there isn't, the code after the last catch block gets executed anyways.
However, the argument against this is that if there is an exception thrown in a catch block, there are no subsequent catch blocks to catch that exception. So by putting resource cleanup code in a finally block, you ensure that resources will be released in the event that an exception is thrown in a catch block.
Which is why the following code puzzles me. I throw an exception in the first catch block and the finally block never executes. Why?
*Please note that there is indeed an exception thrown while creating myStreamReader, as the file is actually called generic.txt and is misspelled with purpose, in order to throw the initial exception.
StreamReader myStreamReader = null;
try
{
myStreamReader = new StreamReader("c:\\genneric.txt");
Console.WriteLine(myStreadReader.ReadToEnd());
}
catch(FileNotFoundException Error)
{
Console.WriteLine(Error.Message);
Console.WriteLine();
throw new Exception();
}
catch(Exception Error)
{
Console.WriteLine(Error.Message);
Console.WriteLine();
}
finally
{
if(myStreamReader != null)
{
myStreamReader.Close();
}
Console.WriteLine("Closed the StreamReader.");
}
VIDEO:
The issue with this block of code originates in this video, at the 27:20 mark:
https://www.youtube.com/watch?v=WxdSb3ZCWYc&list=PLAC325451207E3105&index=41
The guy directly declares that an Exception that occurs in a catch block will not prevent the finally block from executing. I am seeing that it does.
If that new exception is completely unhandled, the entire process is torn down, and the finally block never gets to run.
If there's some other exception handler at a higher level, or an unhandled exception handler has been installed, the finally block does run.
This sample does show "Closed the StreamReader":
static void Main()
{
try
{
StreamReader myStreamReader = null;
try
{
myStreamReader = new StreamReader("c:\\genneric.txt");
Console.WriteLine(myStreamReader.ReadToEnd());
}
catch (FileNotFoundException Error)
{
Console.WriteLine(Error.Message);
Console.WriteLine();
throw new Exception();
}
catch (Exception Error)
{
Console.WriteLine(Error.Message);
Console.WriteLine();
}
finally
{
if (myStreamReader != null)
{
myStreamReader.Close();
}
Console.WriteLine("Closed the StreamReader.");
}
}
catch
{
}
Console.WriteLine("Done");
Console.ReadLine();
}
Unhandled exception handlers can be registered in the AppDomain.UnhandledException event.
Your understanding is not correct. See try-finally.
By using a finally block, you can clean up any resources that are
allocated in a try block, and you can run code even if an exception
occurs in the try block. Typically, the statements of a finally block
run when control leaves a try statement. The transfer of control can
occur as a result of normal execution, of execution of a break,
continue, goto, or return statement, or of propagation of an exception
out of the try statement.
So finally does executed if you return for instance out of a try block, but not if you throw from a catch block.
However, if the exception is unhandled, execution of the finally block
is dependent on how the exception unwind operation is triggered. That,
in turn, is dependent on how your computer is set up.
Assuming the file is not found, it would first catch the FileNotFoundException:
catch(FileNotFoundException error)
{
Console.WriteLine(error.Message);
Console.WriteLine();
throw new Exception();
}
This writes a message to the console, and then throws a new Exception. This exception however, is unhandled and will halt execution. If you throw an exception from within a Catch block, it will not be caught by any subsequent blocks.
The solution is to handle the exception appropiately instead of throwing a new one. If the file was not found, then act upon it, e.g. let the user choose another file, create the file, etc.
use throw instead and try this. When you throw a new exception, the actual exception will be lost. But when you use just throw it will throw the actual exception which is FileNotFoundException.
StreamReader myStreamReader = null;
try
{
myStreamReader = new StreamReader("c:\\genneric.txt");
Console.WriteLine(myStreadReader.ReadToEnd());
}
catch(FileNotFoundException Error)
{
Console.WriteLine(Error.Message);
Console.WriteLine();
throw;
}
catch(Exception Error)
{
Console.WriteLine(Error.Message);
Console.WriteLine();
}
finally
{
Console.WriteLine("Closing the StreamReader.");
try{
if(myStreamReader != null)
{
myStreamReader.Close();
}
} catch(Exception e) { Console.WriteLine(e.ToString()) };
}
}
I have some code like this:
try
{
doStuff();
}
catch(SpecificException)
{
if(e.Message == interestingMessage)
doOtherStuff();
else
throw;
}
catch(Exception e)
{
doSomethingElse();
}
When the first catch block rethrows its exception, will it be caught by the second catch block?
No, if you rethrow the exception you do it to the method caller.
The if inside SpecificException catch would indicates that you need to split that exception into (at least) 2 different types.
I have a try..catch block that looks like this:
try
{
...
}
catch (IOException ioEx)
{
...
}
catch (Exception ex)
{
...
}
I'd like to handle just a certain kind of IOException, namely a sharing violation (Win32 0x20). Other IOExceptions and all other Exception descendants should be handled generally by the second catch-all catch.
Once I know that the IOException is not a sharing violation, how can I cleanly redirect the error handling flow to the general catch? If I rethrow in catch (IOException) the second catch does not invoke. I know I can nest try..catches but is there a cleaner way?
EDIT: On factoring-out handler logic
Factoring repeated code in methods will surely work, but I noticed that in general when you use factored methods for exception handling it tends to have subtle problems.
First of all, a catch clause has direct access to all of the local variables prior to the exception. But when you "outsource" exception handling to a different method then you have to pass the state to it. And when you change the code so does the handler method's signature changes, which might be a maintainability issue in more complicated scenarios.
The other problem is that program flow might be obscured. For example, if the handler method eventually rethrows the exception, the C# compiler and code analyzers like Resharper don't see it:
private void Foo()
{
string a = null;
try
{
a = Path.GetDirectoryName(a);
System.Diagnostics.Debug.Print(a);
}
catch (Exception ex)
{
HandleException(ex, a); //Note that we have to pass the "a"
System.Diagnostics.Debug.Print(
"We never get here and it's not obvious" +
"until you read and understand HandleException"
);
...!
}
}
static void HandleException(Exception ex, string a)
{
if (a != null)
System.Diagnostics.Debug.Print("[a] was not null");
throw (ex); //Rethrow so that the application-level handler catches and logs it
}
VS
private void Bar()
{
string a = null;
try
{
a = System.IO.Path.GetDirectoryName(a);
System.Diagnostics.Debug.Print(a);
}
catch (Exception ex)
{
if (a != null)
System.Diagnostics.Debug.Print("[a] was not null");
throw; //Rethrow so that the application-level handler catches and logs it
System.Diagnostics.Debug.Print(
"We never get here also, but now " +
"it's obvious and the compiler complains"
);
...!
}
}
If I want to avoid these kind of (minor) problems then it seems that there is no cleaner way than nesting try..catch blocks, as Hank pointed out.
Just factor the handling logic into a separate method.
try
{
...
}
catch (IOException ioEx)
{
if (sharing violation)
HandleSharingViolation();
else
HandleNonsharingViolation();
}
catch (Exception ex)
{
HandleNonsharingViolation();
}
Or test the exceptions yourself
catch (Exception ex)
{
if (ex is IOException && ex.IsSharingViolation()
HandleSharingViolation();
else
HandleNonsharingViolation();
}
No, you'll have to nest.
Once you are in 1 of the catch blocks, this 'try' is considered handled.
And I think it may make a lot of sense, "sharing violation" sounds like a special case that probably isn't so tightly coupled to the rest as you might be thinking. If you use nest try-catch, does the try block of the special case has to surround the exact same code? And of course it's a candidate to refactor out as a separate method.
Create Method to handle exception, pass the exception to that method , based on the type Handle the exception in the way you want.Call these method in both these blocks.
Use nested try catch blocks.
try
{
try
{
}
catch (IOException ioEx)
{
if (....)
else
throw;
}
}
catch
{
}
what about "finally"?
you can first set a 'variable' in the IOException block once you know the IOException is not sharing violation. Then, in your finally block, if that 'variable' is set, you proceed to do whatever you need to do.
Below impl. tested and confirmed.
bool booleanValue = false;
try
{
test1(); // this would thro IOException
}
catch (IOException e)
{
booleanValue = true; // whatever you need to do next
}
finally
{
if (booleanValue)
{
Console.WriteLine("Here");
}
}
Tryout this nested block
try
{
}
catch(Exception ioex)
{
try
{
}
catch(Exception ex)
{
}
}
I am confused about the order of try, catch and finally block execution.
I also want to know when should I use try-catch block and what should I put in the try-catch block?
I also want to know if some exception comes in try block then if an action is taken corresponding to try block then which one is executed first catch or finally (which is always to be executed)?
After the execution of these two does control return to try block or it leave it?
If you have (note: this is not valid C#, see below for a valid example):
try {
// ... some code: A
} catch(...) {
// ... exception code: B
} finally {
// finally code: C
}
Code A is going to be executed. If all goes well (i.e. no exceptions get thrown while A is executing), it is going to go to finally, so code C is going to be executed. If an exception is thrown while A is executed, then it will go to B and then finally to C.
As an example, here's a valid C# code block from http://msdn.microsoft.com/en-us/library/dszsf989.aspx:
public class EHClass
{
void ReadFile(int index)
{
// To run this code, substitute a valid path from your local machine
string path = #"c:\users\public\test.txt";
System.IO.StreamReader file = new System.IO.StreamReader(path);
char[] buffer = new char[10];
try
{
file.ReadBlock(buffer, index, buffer.Length);
}
catch (System.IO.IOException e)
{
Console.WriteLine("Error reading from {0}. Message = {1}", path, e.Message);
}
finally
{
if (file != null)
{
file.Close();
}
}
// Do something with buffer...
}
}
The reason to use try/catch/finally is to prevent your program to fail if there is an error in some code (A in the above example). If there is a problem, you can use catch part to catch the problem and do something useful, such as inform the user, log the exception to a log file, try again or try something different that you suppose might work instead of what you tried originally.
finally is used to ensure that some cleanup is performed. E.g. in A you might try to open a file and read it. If opening succeeds, but read fails, you will have an open file dangling. What you would like in that case is to have it closed, which you would do in finally block - this block always gets executed, guaranteeing the closing of the file.
Take a look here for more info:
http://msdn.microsoft.com/en-us/library/0yd65esw.aspx
http://www.c-sharpcorner.com/UploadFile/puranindia/75/Default.aspx
A try ... catch block is used to catch exceptions. In the try block you put the code that you expect may raise an exception.
If no exception occurs then the code in the try block completes as expected. If there's a finally block then that will execute next.
If an exception does occur then execution jumps to the start of the first matching catch block. Once that code is complete the finally block (if it exists) is executed. Execution does not return to the try block.
You should almost never use try/catch.
You should only catch exceptions that you can actually correct, and only when you're expecting them. Otherwise, let the caller handle the exception - or not.
If used, any catch clauses are executed first - only one of them.
Then, finally is "finally" executed.
This has been stated better in many places, but I'll try. The following code:
try
{
// Do something here
}
catch (Exception ex)
{
MessageBox.Show("Friendly error message");
}
does not fix the exception. It hides the exception so that the problem will never be fixed. That code has no idea which exception was thrown, because it will catch all of them, and it does nothing to correct the problem - it just tells the user a polite fiction.
The fact of the matter is that the code above should be replaced with the following:
// Do something here
This way, if the caller of this method knows how to fix particular problems, then the caller can fix them. You will not have removed that option from the caller.
If the caller does not know how to fix the problem, then the caller should also not catch the exception.
Here is an example (from MSDN) of using exceptions in a reasonable manner. It's a modified form of the example in the documentation of the SmtpFailedRecipientsException Class.
public static void RetryIfBusy(string server)
{
MailAddress from = new MailAddress("ben#contoso.com");
MailAddress to = new MailAddress("jane#contoso.com");
using (
MailMessage message = new MailMessage(from, to)
{
Subject = "Using the SmtpClient class.",
Body =
#"Using this feature, you can send an e-mail message from an application very easily."
})
{
message.CC.Add(new MailAddress("Notifications#contoso.com"));
using (SmtpClient client = new SmtpClient(server) {Credentials = CredentialCache.DefaultNetworkCredentials})
{
Console.WriteLine("Sending an e-mail message to {0} using the SMTP host {1}.", to.Address, client.Host);
try
{
client.Send(message);
}
catch (SmtpFailedRecipientsException ex)
{
foreach (var t in ex.InnerExceptions)
{
var status = t.StatusCode;
if (status == SmtpStatusCode.MailboxBusy || status == SmtpStatusCode.MailboxUnavailable)
{
Console.WriteLine("Delivery failed - retrying in 5 seconds.");
System.Threading.Thread.Sleep(5000); // Use better retry logic than this!
client.Send(message);
}
else
{
Console.WriteLine("Failed to deliver message to {0}", t.FailedRecipient);
// Do something better to log the exception
}
}
}
catch (SmtpException ex)
{
// Here, if you know what to do about particular SMTP status codes,
// you can look in ex.StatusCode to decide how to handle this exception
// Otherwise, in here, you at least know there was an email problem
}
// Note that no other, less specific exceptions are caught here, since we don't know
// what do do about them
}
}
}
Note that this code uses try/catch to surround a small piece of code. Within that try/catch block, if an SmtpException or SmtpFailedRecipientsException is thrown, we know what to do about it. If, for instance, we were to catch IOException, we would not know what it meant, or what to do about it. Any exception you don't actually know how to correct should not be caught, except maybe to add information to the exception, log it, and rethrow.
Here is an example:
try
{
someFunctionThatWorks();
functionThatThrowsAnException(); // As soon as this function throws an exception we are taken to the catch block
anotherFunction(); // <-- This line will never get executed
}
catch(Exception e)
{
// Here you can handle the exception, if you don't know how to handle it you should not be catching it
// After this you will not be taken back to the try block, you will go right to the finally block
}
finally
{
// Code here is always executed at the very end, regardless of whether an exception was thrown or not
}
I'd like to elaborate a bit on this and extend #icyrock.com answer with scenario when you rethrow the exception in the catch block so it is handled lower on the execution stack...
I gave it a try with the following code:
static void Main(string[] args)
{
try
{
// pick one:
// NormalExcecution();
// TroubleExcecution();
}
catch
{
Console.WriteLine("block D");
}
Console.ReadKey();
}
private static void NormalExcecution()
{
try
{
Console.WriteLine("block A");
}
catch (Exception)
{
Console.WriteLine("block B");
throw;
}
finally
{
Console.WriteLine("block C");
}
}
private static void TroubleExcecution()
{
try
{
Console.WriteLine("block A");
throw new Exception();
}
catch (Exception)
{
Console.WriteLine("block B");
throw;
}
finally
{
Console.WriteLine("block C");
}
}
So when there is no exception in block A, then the sequence is as follows (exception handling blocks are never hit):
Block A
Block C
When there's some problem with block A, the sequence is as follows:
block A
block B
block C
block D
Another words, the occurring exception is first handled by block B, then the finally clause is executed, only after that the exception is rethrown and handled lower on the execution stack (block D).
Please mind I may be wrong with what is actually going on under the hood of the .NET framework - I just present the results I observed :)
try
{
try
{
throw new Exception("From Try");
}
catch
{
throw new Exception("From Catch");
}
finally
{
throw new Exception("From Finally");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
The above code's output is: From Finally.
Why it's not From Catch?
-or-
How can i catch & log from outside both exceptions?
Because the finally block executes after the catch block, overriding the exception.
And when an exception happens during the handling of an earlier one, the first one is lost.
How can i catch & log from outside both exceptions?
By not throwing inside a finally block. That is always a bad idea.
If you want to log in an inner catch block use throw; or pass the first exception as InnerException of the new one. That is why InnerException exists.
This is the behaviour as it is defined by the C# language specification. Handling of the exception thrown inside the try block is aborted and instead the exception thrown in the finally block will be handled.
The relevant section 8.9.5 The throw statement explains how exceptions are propagates:
In the current function member, each try statement that encloses the throw point is examined. For each statement S, starting with the innermost try statement and ending with the outermost try statement, the following steps are evaluated:
If the try block of S encloses the throw point and if S has one or more catch clauses, the catch clauses are examined in order of appearance to locate a suitable handler for the exception. The first catch clause that specifies the exception type or a base type of the exception type is considered a match. A general catch clause (ยง8.10) is considered a match for any exception type. If a matching catch clause is located, the exception propagation is completed by transferring control to the block of that catch clause.
Otherwise, if the try block or a catch block of S encloses the throw point and if S has a finally block, control is transferred to the finally block. If the finally block throws another exception, processing of the current exception is terminated. Otherwise, when control reaches the end point of the finally block, processing of the current exception is continued.
Add an extra layer of try-catch blocks like the following:
try {
Exception fromCatch = null;
try {
throw new Exception("From Try");
}
catch {
try {
throw new Exception("From Catch");
}
catch (Exception e) {
// catch failed -> store exception
fromCatch = e;
}
}
finally {
try {
throw new Exception("From Finally");
}
catch (Exception e) {
// i can think of better exception merging... but this shows the idea
throw new Exception(e.Message, fromCatch);
}
// throw fromCatch, in case "From Finally did not happen"
throw fromCatch;
}
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
if (ex.InnerException != null) {
Console.WriteLine(ex.InnerException.Message);
}
}
Reports:
From Finally
From Catch
Edit: this is obviously the answer for question two, as the "why" is answered sufficiently :)
finally always runs; and it always runs last. So the lat thing done by the inner try was the finally and that threw something that was caught by the outer catch
not sure if i understand part2 of the question
finally happens no matter what. Regardless of whether there was an exception in the try or catch. Thus, you see "From Finally". (This actually is the entire purpose of the finally clause. So you can put code in there that will clean up resources and the like no matter what -- even if there's an exception.)
Your code throws a new Exception from each part of the try/catch/finally statement. You are essentially swallowing the previous exception when you create the new error. You can add your "From Try" message to your "From Catch" message with something like
catch(Exception ex)
{
throw new Exception(ex.Message + ":" + "From Catch");
}
I don't know know how you could chain that in the finally though.
This is a very good question, and one that is kind of tricky. Let's go through this step by step:
try
{
throw new Exception("From Try");
}
catch
{
throw new Exception("From Catch");
}
In the code above, Exception("From Try") is thrown and caught by the catch clause (pretty simple so far). The catch clause throws an exception of it's own, which normally we would expect (because the catch is nested in a larger try-catch block) to be caught immediately, but...
finally
{
throw new Exception("From Finally");
}
The finally clause, which is guaranteed to (try to) execute, comes first, and throws an exception of it's own, overwriting the Exception("From Catch") that was thrown earlier.
"A common usage of catch and finally
together is to obtain and use
resources in a try block, deal with
exceptional circumstances in a catch
block, and release the resources in
the finally block" - MSDN Article
Following this train of logic, we should try our best to refrain from writing code in our catch and finally blocks that is exception-prone. If you're worried about situations like the one you presented cropping up, I'd recommend logging the exceptions and their related information out to an external file, which you can reference for debugging.
Because the finally block is always executed.
try
{
try
{
throw new Exception("From Try");
// (1) A new exception object A is created here and thrown.
}
catch // (2) Exception object A is catched.
{
throw new Exception("From Catch");
// (3) A new exception object B is created here and thrown.
}
finally // (4) Execution is forced to continue here!
{
throw new Exception("From Finally");
// (5) A new exception object C is created here and thrown.
}
}
catch (Exception ex) // (6) Exception object C is catched.
{
Console.WriteLine(ex.Message);
}
Every new'd exception object in step (3) and (5) discards the previous one. Since the finally block is always executed all what remains is the exception object C from step (5).