This might be a broad question, but recently I ahve wondered about the following: In our C# backend we have many places that wrap some code in a try/catch block, specifically calls to external WcF services. Some of these calls are crucial for the application so in the catch block we log the error and rethrow, like:
catch(Exception ex)
{
_logger.Error("Some good error message");
throw ex;
}
On the other hand there are services we allow to fail, but we still want to log the error, so they look like:
catch(Exception ex)
{
_logger.Error("Some good error message");
}
Now reading the code of team members I can not be sure if they forgot to throw or if this is the intended behaviour.
Q: Is there a way, resp. what is the default way, to explicitly NOT rethrow (without including a comment in the code).
I have considered something like this:
catch(Exception ex)
{
_logger.Error("Some good error message");
NotThrowingHereOnPurpose();
}
// ...
// and further below a private method
// ...
private void NotThrowingHereOnPurpose(){}
One approach that may be useful here is to change the way of invoking the code that you explicitly allow to fail in such a way that it does not look like a try/catch block at all.
For example, you could write a helper method that does error reporting, and call it with actions expressed as lambdas:
void InvokeFailSafe(Action action, Action<Exception> onFailure = null) {
try {
action();
} catch (Exception e) {
if (onFailure != null) {
onFailure(e);
}
}
}
Now instead of try/catch you would write this:
InvokeFailSafe(
() => {
... The code that may fail
}
, exception => _logger.Error("Some good error message: {0}", exception)
);
or like this, if you don't want anything logged:
InvokeFailSafe(
() => {
... The code that may fail
}
);
If you code things this way, there would be no doubts about a missing throw statement.
It's an opposite solution to dasblinkenlight's answer. Instead of notifying others that the exception mustn't be rethrown it would say that it must be.
If you only want to log it then use the Error method as usual. Otherwise, you can write an extension method for your logger to log and throw exceptions.
The method would take the catched exception and rethrow it using the ExceptionDispatchInfo class. The ExceptionDispatchInfo is used to rethrow the exception with the original stack trace information and Watson information. It behaves like throw; (without the specified exception).
public static void ErrorAndThrow(this ILogger logger, string message, Exception exception)
{
var exceptionInfo = ExceptionDispatchInfo.Capture(exception);
logger.Error(message);
exceptionInfo.Throw();
}
And use it this way:
try
{
}
catch (Exception ex)
{
// ex would be rethrown here
_logger.ErrorAndThrow("Some good error message", ex);
}
Q: Is there a way, resp. what is the default way, to explicitly NOT
rethrow (without including a comment in the code).
Ideal way would be not to catch a generic exception. Now, to throw or not that entirely depends on your case. You need to understand that Exception handling is used when you know what to do in case an exception occurs. So, only specific exceptions should be handled. Catching exceptions without knowing what you are catching will change the behavior of your application.
Now reading the code of team members I can not be sure if they forgot
to throw or if this is the intended behaviour.
This is something the author of the code can explain to you. But here is a learning to take from this. Your code should be self explanatory. In specific cases where you are unable to express yourself with the code, add a meaningful comment.
You can check this link for better understanding.
I actually found another way that kind of includes what other have suggested here, but uses a built in feature: exception filters. I was free to modify the example given in here to illustrate this:
public void MethodThatFailsSometimes()
{
try {
PerformFailingOperation();
}
catch (Exception e) when (e.LogAndBeCaught())
{
}
}
and then one could have two extension methods on Exception, say LogAndBeCaught and LogAndEscape like so:
public static bool LogAndBeCaught(this Exception e)
{
_logger.Error(#"Following exception was thrown: {e}");
return true;
}
public static bool LogAndEscape(this Exception e)
{
_logger.Error(#"Following exception was thrown: {e}");
return false;
}
Related
I came across this new feature in C# which allows a catch handler to execute when a specific condition is met.
int i = 0;
try
{
throw new ArgumentNullException(nameof(i));
}
catch (ArgumentNullException e)
when (i == 1)
{
Console.WriteLine("Caught Argument Null Exception");
}
I am trying to understand when this may ever be useful.
One scenario could be something like this:
try
{
DatabaseUpdate()
}
catch (SQLException e)
when (driver == "MySQL")
{
//MySQL specific error handling and wrapping up the exception
}
catch (SQLException e)
when (driver == "Oracle")
{
//Oracle specific error handling and wrapping up of exception
}
..
but this is again something that I can do within the same handler and delegate to different methods depending on the type of the driver. Does this make the code easier to understand? Arguably no.
Another scenario that I can think of is something like:
try
{
SomeOperation();
}
catch(SomeException e)
when (Condition == true)
{
//some specific error handling that this layer can handle
}
catch (Exception e) //catchall
{
throw;
}
Again this is something that I can do like:
try
{
SomeOperation();
}
catch(SomeException e)
{
if (condition == true)
{
//some specific error handling that this layer can handle
}
else
throw;
}
Does using the 'catch, when' feature make exception handling faster because the handler is skipped as such and the stack unwinding can happen much earlier as when compared to handling the specific use cases within the handler? Are there any specific use cases that fit this feature better which people can then adopt as a good practice?
Catch blocks already allow you to filter on the type of the exception:
catch (SomeSpecificExceptionType e) {...}
The when clause allows you to extend this filter to generic expressions.
Thus, you use the when clause for cases where the type of the exception is not distinct enough to determine whether the exception should be handled here or not.
A common use case are exception types which are actually a wrapper for multiple, different kinds of errors.
Here's a case that I've actually used (in VB, which already has this feature for quite some time):
try
{
SomeLegacyComOperation();
}
catch (COMException e) when (e.ErrorCode == 0x1234)
{
// Handle the *specific* error I was expecting.
}
Same for SqlException, which also has an ErrorCode property. The alternative would be something like that:
try
{
SomeLegacyComOperation();
}
catch (COMException e)
{
if (e.ErrorCode == 0x1234)
{
// Handle error
}
else
{
throw;
}
}
which is arguably less elegant and slightly breaks the stack trace.
In addition, you can mention the same type of exception twice in the same try-catch-block:
try
{
SomeLegacyComOperation();
}
catch (COMException e) when (e.ErrorCode == 0x1234)
{
...
}
catch (COMException e) when (e.ErrorCode == 0x5678)
{
...
}
which would not be possible without the when condition.
From Roslyn's wiki (emphasis mine):
Exception filters are preferable to catching and rethrowing because
they leave the stack unharmed. If the exception later causes the stack
to be dumped, you can see where it originally came from, rather than
just the last place it was rethrown.
It is also a common and accepted form of “abuse” to use exception
filters for side effects; e.g. logging. They can inspect an exception
“flying by” without intercepting its course. In those cases, the
filter will often be a call to a false-returning helper function which
executes the side effects:
private static bool Log(Exception e) { /* log it */ ; return false; }
… try { … } catch (Exception e) when (Log(e)) { }
The first point is worth demonstrating.
static class Program
{
static void Main(string[] args)
{
A(1);
}
private static void A(int i)
{
try
{
B(i + 1);
}
catch (Exception ex)
{
if (ex.Message != "!")
Console.WriteLine(ex);
else throw;
}
}
private static void B(int i)
{
throw new Exception("!");
}
}
If we run this in WinDbg until the exception is hit, and print the stack using !clrstack -i -a we'll see the just the frame of A:
003eef10 00a7050d [DEFAULT] Void App.Program.A(I4)
PARAMETERS:
+ int i = 1
LOCALS:
+ System.Exception ex # 0x23e3178
+ (Error 0x80004005 retrieving local variable 'local_1')
However, if we change the program to use when:
catch (Exception ex) when (ex.Message != "!")
{
Console.WriteLine(ex);
}
We'll see the stack also contains B's frame:
001af2b4 01fb05aa [DEFAULT] Void App.Program.B(I4)
PARAMETERS:
+ int i = 2
LOCALS: (none)
001af2c8 01fb04c1 [DEFAULT] Void App.Program.A(I4)
PARAMETERS:
+ int i = 1
LOCALS:
+ System.Exception ex # 0x2213178
+ (Error 0x80004005 retrieving local variable 'local_1')
That information can be very useful when debugging crash dumps.
When an exception is thrown, the first pass of exception handling identifies where the exception will get caught before unwinding the stack; if/when the "catch" location is identified, all "finally" blocks are run (note that if an exception escapes a "finally" block, processing of the earlier exception may be abandoned). Once that happens, code will resume execution at the "catch".
If there is a breakpoint within a function that's evaluated as part of a "when", that breakpoint will suspend execution before any stack unwinding occurs; by contrast, a breakpoint at a "catch" will only suspend execution after all finally handlers have run.
Finally, if lines 23 and 27 of foo call bar, and the call on line 23 throws an exception which is caught within foo and rethrown on line 57, then the stack trace will suggest that the exception occurred while calling bar from line 57 [location of the rethrow], destroying any information about whether the exception occurred in the line-23 or line-27 call. Using when to avoid catching an exception in the first place avoids such disturbance.
BTW, a useful pattern which is annoyingly awkward in both C# and VB.NET is to use a function call within a when clause to set a variable which can be used within a finally clause to determine whether the function completed normally, to handle cases where a function has no hope of "resolving" any exception that occurs but must nonetheless take action based upon it. For example, if an exception is thrown within a factory method which is supposed to return an object that encapsulates resources, any resources that were acquired will need to be released, but the underlying exception should percolate up to the caller. The cleanest way to handle that semantically (though not syntactically) is to have a finally block check whether an exception occurred and, if so, release all resources acquired on behalf of the object that is no longer going to be returned. Since cleanup code has no hope of resolving whatever condition caused the exception, it really shouldn't catch it, but merely needs to know what happened. Calling a function like:
bool CopySecondArgumentToFirstAndReturnFalse<T>(ref T first, T second)
{
first = second;
return false;
}
within a when clause will make it possible for the factory function to know
that something happened.
It's a question about best .net practise. I always caught and stored information about exceptions in all of my web and window forms applications as follows:
Surrounded each method with try catch(Exception exception)
For any layer except front layer, threw exception to the layer above
In the front layer, logged the exception to a log file (usually using log4config.dll) and presented a user friendly message to the user.
Is this the best way to handle exceptions? Or should I do something different in my next projects?
I wouldn't add 1 & 2 unless I had some specific reason; for example to alter (wrap) the message; there is no need since exceptions will raise upwards anyway. And done incorrectly you can accidentally remove the all-important stack-trace (throw; vs throw ex; - the first being preferred).
The following code is problematic because it overwrites the original stack trace for e, which makes problems harder to diagnose:
public void Foo() {
try {
Bar();
} catch(Exception e) {
throw e; // re-throw; overwrites original stacktrace in 'e'
}
}
The following code does not have the above stacktrace overwrite problem, but is still unnecessarily verbose:
public void Foo() {
try {
Bar();
} catch(Exception e) {
throw; // re-throw; preserves original stacktrace in 'e'
}
}
Both would be better written as below. This is because, if the only thing you are doing in your catch block is re-throwing the exception, there is no need to write the catch block at all:
public void Foo() {
Bar();
}
The best answer you can get at Best Practices for Handling Exceptions
Here is how NOT to handle exceptions.
public void method1(){
try{
....
// all the code goes here
// declare any helper methods throw throwable
// eg: private boolean check1() throws Throwable{ ...}
....
}catch(Throwable t){
System.out.println("oops...error...good luck debugging. ");
}
}
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.
Situation:
My application need to process the first step in the business rules (the initial try-catch statement). If an certain error occurs when the process calls the helper method during the step, I need to switch to a second process in the catch statement. The back up process uses the same helper method. If an same error occurs during the second process, I need to stop the entire process and throw the exception.
Implementation:
I was going to insert another try-catch statement into the catch statement of the first try-catch statement.
//run initial process
try
{
//initial information used in helper method
string s1 = "value 1";
//call helper method
HelperMethod(s1);
}
catch(Exception e1)
{
//backup information if first process generates an exception in the helper method
string s2 = "value 2";
//try catch statement for second process.
try
{
HelperMethod(s2);
}
catch(Exception e2)
{
throw e2;
}
}
What would be the correct design pattern to avoid code smells in this implementation?
I caused some confusion and left out that when the first process fails and switches to the second process, it will send different information to the helper method. I have updated the scenario to reflect the entire process.
If the HelperMethod needs a second try, there is nothing directly wrong with this, but your code in the catch tries to do way too much, and it destroys the stacktrace from e2.
You only need:
try
{
//call helper method
HelperMethod();
}
catch(Exception e1)
{
// maybe log e1, it is getting lost here
HelperMethod();
}
I wouldn't say it is bad, although I'd almost certainly refactor the second block of code into a second method, so keep it comprehensible. And probably catch something more specific than Exception. A second try is sometimes necessary, especially for things like Dispose() implementations that might themselves throw (WCF, I'm looking at you).
The general idea putting a try-catch inside the catch of a parent try-catch doesn't seem like a code-smell to me. I can think of other legitimate reasons for doing this - for instance, when cleaning up an operation that failed where you do not want to ever throw another error (such as if the clean-up operation also fails). Your implementation, however, raises two questions for me: 1) Wim's comment, and 2) do you really want to entirely disregard why the operation originally failed (the e1 Exception)? Whether the second process succeeds or fails, your code does nothing with the original exception.
Generally speaking, this isn't a problem, and it isn't a code smell that I know of.
With that said, you may want to look at handling the error within your first helper method instead of just throwing it (and, thus, handling the call to the second helper method in there). That's only if it makes sense, but it is a possible change.
Yes, a more general pattern is have the basic method include an overload that accepts an int attempt parameter, and then conditionally call itself recursively.
private void MyMethod (parameterList)
{ MyMethod(ParameterList, 0)l }
private void MyMethod(ParameterList, int attempt)
{
try { HelperMethod(); }
catch(SomeSpecificException)
{
if (attempt < MAXATTEMPTS)
MyMethod(ParameterList, ++attempt);
else throw;
}
}
It shouldn't be that bad. Just document clearly why you're doing it, and most DEFINITELY try catching a more specific Exception type.
If you need some retry mechanism, which it looks like, you may want to explore different techniques, looping with delays etc.
It would be a little clearer if you called a different function in the catch so that a reader doesn't think you're just retrying the same function, as is, over again. If there's state happening that's not being shown in your example, you should document it carefully, at a minimum.
You also shouldn't throw e2; like that: you should simply throw; if you're going to work with the exception you caught at all. If not, you shouldn't try/catch.
Where you do not reference e1, you should simply catch (Exception) or better still catch (YourSpecificException)
If you're doing this to try and recover from some sort of transient error, then you need to be careful about how you implement this.
For example, in an environment where you're using SQL Server Mirroring, it's possible that the server you're connected to may stop being the master mid-connection.
In that scenario, it may be valid for your application to try and reconnect, and re-execute any statements on the new master - rather than sending an error back to the caller immediately.
You need to be careful to ensure that the methods you're calling don't have their own automatic retry mechanism, and that your callers are aware there is an automatic retry built into your method. Failing to ensure this can result in scenarios where you cause a flood of retry attempts, overloading shared resources (such as Database servers).
You should also ensure you're catching exceptions specific to the transient error you're trying to retry. So, in the example I gave, SqlException, and then examining to see if the error was that the SQL connection failed because the host was no longer the master.
If you need to retry more than once, consider placing an 'automatic backoff' retry delay - the first failure is retried immediately, the second after a delay of (say) 1 second, then doubled up to a maximum of (say) 90 seconds. This should help prevent overloading resources.
I would also suggest restructuring your method so that you don't have an inner-try/catch.
For example:
bool helper_success = false;
bool automatic_retry = false;
//run initial process
try
{
//call helper method
HelperMethod();
helper_success = true;
}
catch(Exception e)
{
// check if e is a transient exception. If so, set automatic_retry = true
}
if (automatic_retry)
{ //try catch statement for second process.
try
{
HelperMethod();
}
catch(Exception e)
{
throw;
}
}
Here's another pattern:
// set up state for first attempt
if(!HelperMethod(false)) {
// set up state for second attempt
HelperMethod(true);
// no need to try catch since you're just throwing anyway
}
Here, HelperMethod is
bool HelperMethod(bool throwOnFailure)
and the return value indicates whether or not success occurred (i.e., false indicates failure and true indicates success). You could also do:
// could wrap in try/catch
HelperMethod(2, stateChanger);
where HelperMethod is
void HelperMethod(int numberOfTries, StateChanger[] stateChanger)
where numberOfTries indicates the number of times to try before throwing an exception and StateChanger[] is an array of delegates that will change the state for you between calls (i.e., stateChanger[0] is called before the first attempt, stateChanger[1] is called before the second attempt, etc.)
This last option indicates that you might have a smelly setup though. It looks like the class that is encapsulating this process is responsible for both keeping track of state (which employee to look up) as well as looking up the employee (HelperMethod). By SRP, these should be separate.
Of course, you need to a catch a more specific exception than you currently are (don't catch the base class Exception!) and you should just throw instead of throw e if you need to rethrow the exception after logging, cleanup, etc.
You could emulate C#'s TryParse method signatures:
class Program
{
static void Main(string[] args)
{
Exception ex;
Console.WriteLine("trying 'ex'");
if (TryHelper("ex", out ex))
{
Console.WriteLine("'ex' worked");
}
else
{
Console.WriteLine("'ex' failed: " + ex.Message);
Console.WriteLine("trying 'test'");
if (TryHelper("test", out ex))
{
Console.WriteLine("'test' worked");
}
else
{
Console.WriteLine("'test' failed: " + ex.Message);
throw ex;
}
}
}
private static bool TryHelper(string s, out Exception result)
{
try
{
HelperMethod(s);
result = null;
return true;
}
catch (Exception ex)
{
// log here to preserve stack trace
result = ex;
return false;
}
}
private static void HelperMethod(string s)
{
if (s.Equals("ex"))
{
throw new Exception("s can be anything except 'ex'");
}
}
}
Another way is to flatten the try/catch blocks, useful if you're using some exception-happy API:
public void Foo()
{
try
{
HelperMethod("value 1");
return; // finished
}
catch (Exception e)
{
// possibly log exception
}
try
{
HelperMethod("value 2");
return; // finished
}
catch (Exception e)
{
// possibly log exception
}
// ... more here if needed
}
An option for retry (that most people will probably flame) would be to use a goto. C# doesn't have filtered exceptions but this could be used in a similar manner.
const int MAX_RETRY = 3;
public static void DoWork()
{
//Do Something
}
public static void DoWorkWithRetry()
{
var #try = 0;
retry:
try
{
DoWork();
}
catch (Exception)
{
#try++;
if (#try < MAX_RETRY)
goto retry;
throw;
}
}
In this case you know this "exception" probably will happen so I would prefer a simple approach an leave exceptions for the unknown events.
//run initial process
try
{
//initial information used in helper method
string s1 = "value 1";
//call helper method
if(!HelperMethod(s1))
{
//backup information if first process generates an exception in the helper method
string s2 = "value 2";
if(!HelperMethod(s2))
{
return ErrorOfSomeKind;
}
}
return Ok;
}
catch(ApplicationException ex)
{
throw;
}
I know that I've done the above nested try catch recently to handle decoding data where two third party libraries throw exceptions on failure to decode (Try json decode, then try base64 decode), but my preference is to have functions return a value which can be checked.
I generally only use the throwing of exceptions to exit early and notify something up the chain about the error if it's fatal to the process.
If a function is unable to provide a meaningful response, that is not typically a fatal problem (Unlike bad input data).
It seems like the main risk in nested try catch is that you also end up catching all the other (maybe important) exceptions that might occur.
I have a couple questions about exceptions.
1) when you hit a catch block, swallowing means what exactly? I thought it was always rethrow or the existing exceptions is passed up to the next catch block.
2) If you add Exception.Data values to an excepction, I notice I have to do another throw; to grab that data futher up in another catch block later. Why?
Swallowing an exception means catching it and not doing anything useful with it. A common thing you might see is this:
try
{
DoSomeOperationThatMightThrow();
}
catch (Exception ex) // don't do this!
{
// exception swallowed
}
You usually don't want to catch a base Exception at all, it's better to catch and handle specific Exception types, and ideally you should only catch exception types that you can do something useful with at the level of code you're in. This can be tricky in complex applications, because you might be handling different errors at different levels in the code. The highest level of code might just catch serious/fatal exceptions, and lower levels might catch exceptions that can be dealt with with some error handling logic.
If you do catch an exception and need to rethrow it, do this:
try
{
DoSomething();
}
catch (SomeException ex)
{
HandleError(...);
// rethrow the exception you caught
throw;
// Or wrap the exception in another type that can be handled higher up.
// Set ex as the InnerException on the new one you're throwing, so it
// can be viewed at a higher level.
//throw new HigherLevelException(ex);
// Don't do this, it will reset the StackTrace on ex,
// which makes it harder to track down the root issue
//throw ex;
}
Swallowing an exception normally means having a handling block for the exception, but not doing anything in the block. For example:
try { 3/0; } catch DivideByZeroException { //ignore } //Note: I know this really wont' compile because the compiler is smart enough to not let you divide by a const of 0.
You have to rethrow because the first handler for an exception is the only one that will execute.
If you want the exception to bubble up you either don't handle it or you rethrow it. By the way, it's important to note that in .NET by just saying "throw" you'll preserve the stack trace. If you "throw Exception" you'll lose your stack trace.
Ok, you can handle the exception up to call stack you can do some thing like this:
public class A
{
public void methodA()
{
try
{
}
catch(Exception e)
{
throw new Exception("Some description", e);
}
}
}
public class B
{
public void methodB()
{
try
{
A a = new A();
a.methodA();
}
catch(Exception e)
{
//...here you get exceptions
}
}
}