Consider the following:
try {
FileStream fileStream = new FileStream("C:\files\file1.txt", FileMode.Append); }
catch (DirectoryNotFoundException e)
{ MessageBox.Show("Directory not found. " + e.Message); }
catch (IOException e)
{ MessageBox.Show("Other IO Error. " + e.Message); }
catch (Exception e)
{ MessageBox.Show("Other Error. " + e.Message); }
Will a DirectoryNotFoundException exception get handled by all three catch clauses or just the first one?
Just the first one. The exception doesn't propagate to all matching catch clauses.
From the C# 4 spec, section 8.9.5:
The first catch clauses that specifies the exception type or a base type of the exception type is considered a match. [...] If a matching catch clause is located, the exception propagation is completed by transferring control to the block of that catch clause.
Here the "completed" part indicates that after control has been transferred, that's the end of the special handling, effectively.
Only the first one. Catch-blocks doesn't fall through.
Only the first matching catch catches the exception, should you for any reason need to cacth it again you will have to throw it again so the "external" catch caluses will be able to catch it.
only the 1st one , the 1st matching catch clause will handle the exception
This is the correct way to handle exceptions - start with the most specific exception type and work back. Bare in mind however, if you can't do anything to resolve or handle an exception, don't catch it. For example, I'm assuming your code is in some file-access method, I would remove the last catch (Exception) block, as there's nothing you can do about it here (what if it's a stack overflow, out of memory or some other serious system exception...)
Related
I want a better way to catch database error details.
I'm currently using :
try
{
dbconn.table.AddObject(newRow);
dbconn.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine("DB fail ID:" + Row.id);
}
many times I found the Exception ex can no give me details on how the exception happen.
I think these exception most likely to be the DB connection kind.
So is there a better way to catch this ?
You should also output the exception. Most of the time, it holds useful and detailed information (e.g. names of violated constraints). Try this:
try
{
dbconn.table.AddObject(newRow);
dbconn.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine("DB fail ID:" + Row.id);
Console.WriteLine(ex.ToString());
}
For full details, use the ToString() method, it will give you the stack trace as well, not only the error message.
Use Console.WriteLine(ex.GetType().FullName) (or put a breakpoint and run under a debugger) to see the actual exception type being thrown. Then visit MSDN to see its description and base classes. You need to decide which of the base classes provides you with the information needed by exposing such properties. Then use that class in your catch() expression.
For Entity Framework, you might end up with using EntityException and then checking the InnerException property for the SQL exception object that it wraps.
try
{
dbconn.table.AddObject(newRow);
dbconn.SaveChanges();
}
catch (EntityException ex)
{
Console.WriteLine("DB fail ID:" + Row.id + "; Error: " + ex.Message);
var sqlExc = ex.InnerException as SqlException;
if (sqlExc != null)
Console.WriteLine("SQL error code: " + sqlExc.Number);
}
Instead of Exception use SqlException.
SqlException give you more detail. it has a Number property that indicate type of error and you can use that Number in a switch case to give some related information to user.
In short, yes there is a better way to handle it. The 'how' of it is up to you.
Exception handling in C# goes from the most specific exception type to the least specific. Also, you aren't limited to using just one catch block. You can have many of them.
As an example:
try
{
// Perform some actions here.
}
catch (Exception exc) // This is the most generic exception type.
{
// Handle your exception here.
}
The above code is what you already have. To show an example of what you may want:
try
{
// Perform some actions here.
}
catch (SqlException sqlExc) // This is a more specific exception type.
{
// Handle your exception here.
}
catch (Exception exc) // This is the most generic exception type.
{
// Handle your exception here.
}
In Visual Studio, it is possible to see a list of (most) exceptions by pressing CTRL+ALT+E.
I have seen such code in many places, is there any benefit of this..Or this is a wrong practice..
try
{
......
}
catch (NullReferenceException ex)
{
Data.LogError(ex, "Exception occourred while ...");
}
catch (IndexOutOfRangeException ex)
{
Data.LogError(ex, "Exception occourred while ...");
}
catch (Exception ex)
{
Data.LogError(ex, "Exception occourred while ...");
}
In context of specific exception handling.
There is benefit if you are going to handle the exceptions differently in the catch block (i.e. perform different actions as a result of the exception being thrown).
Otherwise you could remove the more specific exception handlers and just use the most generic:
catch(Exception ex)
Note: If the exception is being used purely for logging then sometimes it can be useful to re-throw the exception to bubble it up to the rest of the application:
try{
}
catch(Exception ex){
// Log exception here
throw;
}
This is even better than a generic catch, because you can choose what to do with a certain type of exception. Say, you want to show a message if a file doesn't exist, and offer to retry, but kill the application otherwise.
You can also handle exceptions differently, because they offer different properties (thanks to Rots for pointing that out):
try
{
}
catch(FileNotFoundException ex)
{
Console.WriteLine(ex.FileName + " not found");
//Retry
}
catch(Exception ex) // Exception does not contain ex.FileName
{
//Save stuff
//Exit
}
Only the first matching block will be executed.
The given approach is best in case if you wanted to handle/log any specific exception in it's own way. Also, ideal in scenario, where you can inform user with more apt details than giving generic messages. Now, if you don't want to handle different exceptions then you can goahead with one catch block, which catch all exception.
Newby question...
Is it valid to do:
try
{
// code which may fail
}
catch
{
Console.Writeline("Some message");
}
Or do I always have to use:
try
{
// code which may fail
}
catch (Exception e)
{
Console.Writeline("Some message");
}
Both blocks are valid.
The first will not have an exception variable.
If you are not going to do anything with the exception variable but still want to catch specific exceptions, you can also do:
try
{
// your code here
}
catch(SpecificException)
{
// do something - perhaps you know the exception is benign
}
However, for readability I would go with the second option and use the exception variable. One of the worst things to do with exceptions is swallow them silently - at the minimum, log the exception.
Yep, absolutely, such a catch block called general catch clause, see more interesting details in the C# Language Specification 4.0, 8.10 The try statement:
A catch clause that specifies neither an exception type nor an
exception variable name is called a general catch clause. A try
statement can only have one general catch clause, and if one is
present it must be the last catch clause
Yes, your first block of code valid. It will catch all exceptions.
It is. It will catch all the exception. So the two code examples do the same.
First one is valid, and it acts just like the second one.
http://msdn.microsoft.com/en-us/library/0yd65esw%28v=vs.80%29.aspx
The catch clause can be used without arguments, in which case it
catches any type of exception, and referred to as the general catch
clause. It can also take an object argument derived from
System.Exception, in which case it handles a specific exception.
Yes it is valid.
you can always refer to this article:
Best Practices for Handling Exceptions on MSDN
Of course it is valid, you specify catch(Exception e) when you want to output the error message ex.Message, or to catch a custom or a concrete Exception. Use catch in your situation.
As #David answered this is valid.
You could use second syntax if you want to get more infos or catch a specific exception.
E.g.
catch (Exception e)
{
Debug.Print(e.Message);
}
catch (Exception e)
{
Console.Writeline("Some message");
}
In this block you can use SqlException, etc..
catch (SqlException e)
{
Console.Writeline("Some message");
}
For this use the "(SqlException e)"
If you will use a generic menssage, use this:
catch
{
Console.Writeline("Some message");
}
or
catch (Exception)
{
Console.Writeline("Some message");
}
Don't forget that you can chain catch your exceptions. This will allow you to handle different scenarios based upon the exception(s) the code may throw.
try
{
//Your code.
}
catch(SpecificException specificException)
{
//Handle the SpecificException
}
catch(AnotherSpecificException anotherSpecificException)
{
//Handle AnotherSpecificException
}
catch(Exception exception)
{
//Handle any Exception
}
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).
This is a bit abstract, but is there any possible way to throw an exception and have it enter multiple catch blocks? For example, if it matches a specific exception followed by a non-specific exception.
catch(Arithmetic exception)
{
//do stuff
}
catch(Exception exception)
{
//do stuff
}
It is perfectly acceptable to have multiple catch blocks of differring types. However, the behavior is that the first candidate block handles the exception.
It will not enter BOTH catch blocks. The first catch block that matches the exception type will handle that specific exception, and no others, even if it's rethrown in the handler. Any subsequent ones will be skipped once an exception enters a catch block.
In order to have an exception caught in BOTH blocks, you would need to either nest blocks like so:
try
{
try
{
// Do something that throws ArithmeticException
}
catch(ArithmeticException arithException)
{
// This handles the thrown exception....
throw; // Rethrow so the outer handler sees it too
}
}
catch (Exception e)
{
// This gets hit as well, now, since the "inner" block rethrew the exception
}
Alternatively, you could filter in a generic exception handler based on the specific type of exception.
No. It isn't possible to execute the code in both catch blocks for a single exception.
I would probably refactor the code in the generic exception block into something that can be called from either.
try
{
// blah blah blah
{
catch(Arithmetic ae)
{
HandleArithmeticException( ae );
HandleGenericException( ae );
}
catch(Exception e)
{
HandleGenericException( e );
}
Like others said the exception will be caught by the most specific catch block.
This brings up a frustration of mine though with exception handling. I wish you could do something like
catch (ArgumentNullExcpetion, ArugmentOutOfRangeException ex)
{
}
Instead of having to do
catch (ArgumentNullExcpetion e)
{
}
catch (ArugmentOutOfRangeException outOfRange)
{
}
I understand the reasoning against this that you probably do different things for different exceptions but sometimes I want combine them.
You can't have more than one exception block handle the same exception. But what you can do is catch the general exception, then attempt to cast to the more specific, like this:
catch (Exception exception)
{
var aex = exception as ArithmeticException
if (aex != null)
{
// do stuff specific to this exception type
}
// then do general stuff
}
If you were using VB.NET you could abstract your error handler in the Arithmetic exception into a function or method call that always returns false.
Then you could write something like:
Catch ex as Arithmetic When HandleArithmetic()
Catch ex as Exception
End Try
Not that I would advocate such usage, though I have seen it recommended for logging purposes before. I don't believe there is a C# equivalent.
This is known as exception filtering and isn't supported in C# (I'm told it is possible in VB.NET).
One work around would be to catch the general exception and then check the exception type in the catch block and do any specific processing on that before carrying on with the rest of the block.