Reuse catch for all catches - c#

is it possible to do something like the following:
I want to catch a custom exception and do something with it - easy: try {...} catch (CustomException) {...}
But then i want to run the code used in the "catch all" block still run some other code which is relevant to all catch blocks...
try
{
throw new CustomException("An exception.");
}
catch (CustomException ex)
{
// this runs for my custom exception
throw;
}
catch
{
// This runs for all exceptions - including those caught by the CustomException catch
}
or do i have to put whatever i want to do in all exception cases (finally is not an option because i want it only to run for the exceptions) into a separate method/nest the whole try/catch in another (euch)...?

I generally do something along the lines of
try
{
throw new CustomException("An exception.");
}
catch (Exception ex)
{
if (ex is CustomException)
{
// Do whatever
}
// Do whatever else
}

You need to use two try blocks:
try
{
try
{
throw new ArgumentException();
}
catch (ArgumentException ex)
{
Console.WriteLine("This is a custom exception");
throw;
}
}
catch (Exception e)
{
Console.WriteLine("This is for all exceptions, "+
"including those caught and re-thrown above");
}

Just do the overall catch and check to see if the exception is that type:
try
{
throw new CustomException("An exception.");
}
catch (Exception ex)
{
if (ex is CustomException)
{
// Custom handling
}
// Overall handling
}
Alternately, have a method for overall exception handling that both call:
try
{
throw new CustomException("An exception.");
}
catch (CustomException ex)
{
// Custom handling here
HandleGeneralException(ex);
}
catch (Exception ex)
{
HandleGeneralException(ex);
}

No, it doesn't do this way, you either catch a specific exception (linearly) or a generalisation. If you wish to run something for all exceptions you would need to keep a record of whether or not an exception has been thrown, perhaps what it was etc, and use finally, or another contrived, probably more 'messy' and verbose, mechanism.

Related

How to catch a rethrown exception?

I have the following code:
try
{
await _policyService.QueuePayment();
}
catch (Exception ex)
{
var slackError = new ErrorNotificationMessage("{ex.Message}");
await Notify(slackError);
}
I want to give more detail and log it to Slack if the Exception is a Security Exception, so I extended this try/catch block as follows:
try
{
await _policyService.QueuePayment();
}
catch (SecurityException ex)
{
throw new Exception("detailed message", ex);
}
catch (Exception ex)
{
var slackError = new ErrorNotificationMessage("{ex.Message}");
await Notify(slackError);
}
However this does not catch the rethrown Exception and log it to Slack. What am I missing here?
As it was already mentioned in comments by #canton7, you'd need a try-catch inside the catch (SecurityException ex) in order to catch it. However, as it was also mentioned, that doesn't make sense here. It's also not a common (or rather, correct) practice to wrap an exception just to change the error message.
Just use standard boolean logic:
try
{
await _policyService.QueuePayment();
}
catch (Exception ex)
{
var message = ex is SecurityException ? "Some very important message" : ex.Message;
var slackError = new ErrorNotificationMessage(message);
await Notify(slackError);
}
However this does not catch the rethrown Exception and log it to Slack. What am I missing here?
When we throw an exception explicitly it can be catched at the caller end by enclosing the method call in a try catch block. We cannot throw and catch the exception from a catch block in same method unless we add another try catch which does not actually make sense here.
What you should be doing is directly throwing that exception like :
try
{
await _policyService.QueuePayment();
}
catch (Exception ex)
{
if(ex is SecurityException)
{
// for security exception do something different
}
else
{
var slackError = new ErrorNotificationMessage("{ex.Message}");
await Notify(slackError);
}
}

Throwing Exceptions Correctly

I have the following code
public HttpResponseMessage AddDataToDatabase([FromBody] Data data)
{
try
{
var token = _tokenService.GetToken(Request.Headers.Authorization);
if (_pService.Permission(_tokenService.GetUserId(token), "Enable_Data"))
{
_noteService.AddData(data, _tokenService.GetUserId(token));
return Request.CreateResponse(HttpStatusCode.OK, "Data has been added to the case.");
}
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.Forbidden, "Cannot add data because you don't have permission."));
}
catch (Exception exception)
{
if (exception is SqlException)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, exception));
}
if (exception is ArgumentException)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.Conflict, exception.Message));
}
throw;
}
}
I want to catch the Forbidden Exception like other exception in the catch block but not sure how to do that. The way I am returning Forbidden exception right now breaks unit tests which return SqlException and ArgumentExpception.
How can I throw exceptions correctly?
By far, the easiest way is to simply do it like this.
catch (Exception exception)
{
throw;
}
Unlike your code, this code also handles unanticipated exceptions instead of just SqlException and ArgumentException.
But why are you doing this? If you want the exception to propagate out to the caller, then simply remove the try...catch block in this method. Then just throw the desired exception in your code.
If you are capturing and converting third-party exceptions, the recommended approach is as follows.
catch (SqlException exception)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, exception));
}
catch (ArgumentException exception)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.Conflict, exception.Message));
}
you should probably replace your if logic in your catch by using more selective catch :
catch (SqlException exception)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, exception));
}
catch (ArgumentException exception)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.Conflict, exception.Message));
}
The uncaught exceptions will simplypass through (as when you you use throw;).
If you want to catch another type of exception, just add it to the list.
However, it is not very clear how your tests are broken. You should provide more details at this level if you want more help.

What is the advantage of using Exception filters and when should I use them?

Comparing the old way versus the new way of error handling, by using Exception filters, what is exactly the advantage for me of using filters and when should I use it? is there an scenario where I can get a good advantage of this new feature?
I have read about the unwinding stack but still I don't get the scenario where we can not handle that under the old way. Explain like I'm 5 please.
try
{
Foo.DoSomethingThatMightFail(null);
}
catch (MyException ex) when (ex.Code == 42)
{
Console.WriteLine("Error 42 occurred");
}
vs
try
{
Foo.DoSomethingThatMightFail(null);
}
catch (MyException ex)
{
if (ex.Code == 42)
Console.WriteLine("Error 42 occurred");
else
throw;
}
I know there is other version of this question, the problem is, that the question mention benefits that I cant actually find, for instance.
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.
after doing some testing, I did not see the difference between both, I still see the exception from the place it was rethrown. So, or the information is not confirmed, I don't understand the Exception filters( that is why I am asking), or I am doing it wrong (also please correct me if I am wrong).
class specialException : Exception
{
public DateTime sentDateTime { get; } = DateTime.Now;
public int code { get; } = 0;
public string emailsToAlert { get; } = "email#domain.com";
}
then:
try
{
throw new specialException();
//throw new Exception("Weird exception");
//int a = Int32.Parse("fail");
}
catch (specialException e) when(e.code == 0)
{
WriteLine("E.code 0");
throw;
//throw e;
}
catch (FormatException e)
{
if (cond1)
{
WriteLine("cond1 " + e.GetBaseException().Message+" - "+e.StackTrace);
throw;
}
throw;
}
catch (Exception e) //when (cond2)
{
Console.WriteLine("cond2! " + e.Message);
throw;
}
I don't understand Paulo's answer. He may be correct or he may not be.
I definitely disagree with Alexander's answer. It is not just syntactic sugar. Pure syntactic sugar means it's solely an easier way of writing something, and that execution will be unchanged.
However, that's not the case in this situation. As Thomas Levesque points out in his blog, exception filters do not unwind the stack. So when debugging the program, if you have an exception thrown in your try block, with exception filters you'll be able to see what the state of the values are in the try block. If you weren't using exception filters, your code would enter the catch block and you would lose information about the state of the variables in the try block.
Note that I'm not talking about the stacktrace (it's a different but related concept to the stack). The stacktrace would be unchanged unless you explicitly did rethrow the exception as in throw exception; in a catch block where exception is the caught exception.
So while in some cases you can think of it as something that may or may not make your code cleaner (depending on your opinion of the syntax), it does change the behavior.
Exception filters have been added to C# because they were in Visual Basic and the "Roslyn" team found them useful when developing "Roslyn".
Beware that the filter runs in the context of the throw and not in the context of the catch.
Anyhow, one use might be something like this:
try
{
//...
}
catch (SqlException ex) when (ex.Number == 2)
{
// ...
}
catch (SqlException ex)
{
// ...
}
Edited:
One might think this is just syntactic sugar over this:
try
{
//...
}
catch (SqlException ex) when (ex.Number == 2)
{
// ...
}
catch (SqlException ex)
{
if (ex.Number == 2)
{
// ...
}
else
{
// ...
}
}
But if we change the code for this:
try
{
//...
}
catch (SqlException ex) when (ex.Number == 2)
{
// ...
}
It will be more like this:
try
{
//...
}
catch (SqlException ex) when (ex.Number == 2)
{
// ...
}
catch (SqlException ex)
{
if (ex.Number == 2)
{
// ...
}
else
{
throw
}
}
But there's one fundamental difference. The exception is not caught and rethrown if ex.Number is not 2. It's just not caught if ex.Number is not 2.
UPD: As pointed out in the answer by Paulo Morgado, the feature has been in CLR for quite some time and C# 6.0 only added syntax support for it. My understanding of it, however, remains as a syntactic sugar, e.g. the syntax that allows me to filter exceptions in a nicer way than it used to be, irrespective of how the previous "straightforward" method works under the hood.
=====
In my understanding, this is a syntactic sugar that allows you to more clearly define the block there your exception is going to be handled.
Consider the following code:
try
{
try
{
throw new ArgumentException() { Source = "One" };
throw new ArgumentException() { Source = "Two" };
throw new ArgumentException() { Source = "Three" };
}
catch (ArgumentException ex) when (ex.Source.StartsWith("One")) // local
{
Console.WriteLine("This error is handled locally");
}
catch (ArgumentException ex) when (ex.Source.StartsWith("Two")) // separate
{
Console.WriteLine("This error is handled locally");
}
}
catch (ArgumentException ex) // global all-catcher
{
Console.WriteLine("This error is handled globally");
}
Here you can clearly see that first and second exception are handled in the respective blocks that are separated using when safeguard, whereas the one global catch-all block will catch only the third exception. The syntax is clearer that catching all the exceptions in every block, something like:
catch (ArgumentException ex) // local
{
if (ex.Source.StartsWith("One"))
{
Console.WriteLine("This error is handled locally");
}
else
{
throw;
}
}

Catch two exceptions in the same catch block?

I have a method that can throw two different exceptions, CommuncationException and SystemException. In both cases I do the same three-line code block.
try {
...
}
catch (CommunicationException ce) {
...
}
catch {SystemExcetion se) {
...
}
Is there any possibility to do it like that?
try {
...
}
catch (CommunicationException ce, SystemException se) {
...
}
Then I would not have to write this much code. I know I could extract the exception handling to a private method, but since the code is only 3 lines long, the method definition would take more code than the body itself.
If you can upgrade your application to C# 6 you are lucky. The new C# version has implemented Exception filters. So you can write this:
catch (Exception ex) when (ex is CommunicationException || ex is SystemException) {
//handle it
}
Some people think this code is the same as
catch (Exception ex) {
if (ex is CommunicationException || ex is SystemException) {
//handle it
}
throw;
}
But it´s not. Actually this is the only new feature in C# 6 that is not possible to emulate in prior versions. First, a re-throw means more overhead than skipping the catch. Second, it is not semantically equivalent. The new feature preserves the stack intact when you are debugging your code. Without this feature the crash dump is less useful or even useless.
See a discussion about this on CodePlex. And an example showing the difference.
In fact, you could catch only SystemException and it would handle CommunicationException too, because CommunicationException is derived from SystemException
catch (SystemException se) {
... //this handles both exceptions
}
Unfortunately, there is no way. The syntax you used is invalid and a fall through like in a switch-statement isn't possible either. I think you need to go with the private method.
A little hacky work-around would be something like this:
var exceptionHandler = new Action<Exception>(e => { /* your three lines */ });
try
{
// code that throws
}
catch(CommuncationException ex)
{
exceptionHandler(ex);
}
catch(SystemException ex)
{
exceptionHandler(ex);
}
You need to decide for yourself if this makes any sense.
No, you can't do it that way. The only way i know of is to catch a generic Exception and then check what type it is:
try
{
...
}
catch(Exception ex)
{
if(ex is CommunicationException || ex is SystemException)
{
...
}
else
{
... // throw; if you don't want to handle it
}
}
What about
try {
...
}
catch (CommunicationException ce) {
HandleMyError(ce);
}
catch {SystemExcetion se) {
HandleMyError(se);
}
private void HandleMyError(Exception ex)
{
// handle your error
}
Possible Duplicate of
Catch multiple exceptions at once?
I quote the answer here:
catch (Exception ex)
{
if (ex is FormatException ||
ex is OverflowException)
{
WebId = Guid.Empty;
return;
}
else
{
throw;
}
}
Dragging this one up from the depths of history as it happened to pop up in some search results.
With the advent of C# 7.0 (which arrived in 2017 with VS2017, .net framework 4.7 and dotnet core 2.0) you can now do things like this:
try {
...
}
catch (Exception e) when (e is CommunicationException || e is SystemException) {
...
}
Since you're doing the same for both type of exceptions, you could just go:
try
{
//do stuff
}
catch(Exception ex)
{
//normal exception handling here
}
Only catch explicit Exception types if you need to do something unique for it.

Is the order of Catch blocks important?

Just making sure I understand it well. Is the correct schema correct? Catching the most specific exceptions first to catching broader exceptions with general catch at the end of the set of catch blocks.
try
{
some code
}
catch(SomeSpecificException ex)
{
}
catch(LessSpecificException ex)
{
}
catch
{
//some general exception
}
I believe it won't let you write it in the incorrect order.
This generates an error:
try
{
throw new OutOfMemoryException();
}
catch(Exception ex)
{
"B".Dump();
}
catch(OutOfMemoryException ex)
{
"A".Dump();
}

Categories

Resources