Why catch and rethrow an exception in C#?
Asked Answered
M

18

719

I'm looking at the article C# - Data Transfer Object on serializable DTOs.

The article includes this piece of code:

public static string SerializeDTO(DTO dto) {
    try {
        XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
        StringWriter sWriter = new StringWriter();
        xmlSer.Serialize(sWriter, dto);
        return sWriter.ToString();
    }
    catch(Exception ex) {
        throw ex;
    }
}

The rest of the article looks sane and reasonable (to a noob), but that try-catch-throw throws a WtfException... Isn't this exactly equivalent to not handling exceptions at all?

Ergo:

public static string SerializeDTO(DTO dto) {
    XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
    StringWriter sWriter = new StringWriter();
    xmlSer.Serialize(sWriter, dto);
    return sWriter.ToString();
}

Or am I missing something fundamental about error handling in C#? It's pretty much the same as Java (minus checked exceptions), isn't it? ... That is, they both refined C++.

The Stack Overflow question The difference between re-throwing parameter-less catch and not doing anything? seems to support my contention that try-catch-throw is-a no-op.


EDIT:

Just to summarise for anyone who finds this thread in future...

DO NOT

try {
    // Do stuff that might throw an exception
}
catch (Exception e) {
    throw e; // This destroys the strack trace information!
}

The stack trace information can be crucial to identifying the root cause of the problem!

DO

try {
    // Do stuff that might throw an exception
}
catch (SqlException e) {
    // Log it
    if (e.ErrorCode != NO_ROW_ERROR) { // filter out NoDataFound.
        // Do special cleanup, like maybe closing the "dirty" database connection.
        throw; // This preserves the stack trace
    }
}
catch (IOException e) {
    // Log it
    throw;
}
catch (Exception e) {
    // Log it
    throw new DAOException("Excrement occurred", e); // wrapped & chained exceptions (just like java).
}
finally {
    // Normal clean goes here (like closing open files).
}

Catch the more specific exceptions before the less specific ones (just like Java).


References:

Minus answered 19/5, 2009 at 7:56 Comment(11)
Good summary; extra points for including the finally block.Wallack
i would like to add that you can use the "throw;" to be even more helpful by adding the parameters that were sent to the method in the e.Data collection before the "throw;" statementEducational
@MickTheWarMachineDesigner (and part-time painter). Huh? You're talking handling Microshite Suckwell (proabably 2005 onwards, for all I know) exceptions. I was talking about exception handling in general. And yes I've learned some since I posted this NEARLY FOUR YEARS AGO.... But yes, I confess that you have valid point, but me thinks you've missed the real point; if you get my drift? This question is about GENERALISED exception handling in C#; and more specifically about rethrowing exceptions... of ALL kinds. Cool?Minus
Please consider moving the edit summary section in your question to its own answer. For why, see Editing self-answer out of question and Answer embedded in question.Kendall
It seems sensible to catch and throw new exceptions when wrapping a third party module, as it removes the dependencies on that module throughout your solution. Some examples in "Adaptive Code via C#" explain this well, with good justifications I believe. Your first example isn't a good example of this however.Preindicate
Did anyone not notice the "Excrement occurred" part? it sounds like the code went for a poop!Outsert
@Minus why should be put throw at the end of catch block? what's purpose of that throw? isn't logger enoght like lets log the exception and life goes on :DPraseodymium
So the difference between preserving the trace stack and throwing it away is the exception object that's included with the throw statement e.g., throw versus throw e? Or does it have to do with the type of exception thrown i.e., does throw aSqlException preserve the stack trace?Wing
Since .NET 4.5 there is one more way: ExceptionDispatchInfo.Capture(ex).Throw() https://mcmap.net/q/40923/-how-to-rethrow-innerexception-without-losing-stack-trace-in-cBouncer
There can be cases where you do not want to bloat your log files with stack traces. In my case the exception was about "half done" configuration in my system, and I just want to log something like this "Can't bla bla, please verify your settings."Valerio
Like fishing, sometimes its better to catch and releaseMaomaoism
P
546

First, the way that the code in the article does it is evil. throw ex will reset the call stack in the exception to the point where this throw statement is losing the information about where the exception actually was created.

Second, if you just catch and re-throw like that, I see no added value. The code example above would be just as good (or, given the throw ex bit, even better) without the try-catch.

However, there are cases where you might want to catch and rethrow an exception. Logging could be one of them:

    try 
    {
        // code that may throw exceptions    
    }
    catch(Exception ex) 
    {
        // add error logging here
        throw;
    }
Phosphoresce answered 19/5, 2009 at 8:2 Comment(14)
@Fredrick, just fyi (though you probably know) if you're not going to use that ex object, then there's no need to instantiate it.Flunky
@Eoin: I am aware of that. In this case I suggested to catch the exception in order to do something (such as logging) with it before rethrowing, and then I will need the exception instance. Good point though.Wallack
@Eoin: If its not instantiated it'd be rather difficult to log it.California
@Fredrik: I think 'evil' is a little bit strong. It might not be very useful to do throw ex, but there are no negative side-effects when you do so other than losing the call stack information.Paba
@divo; yes, it's a bit strong, agreed. But I have seen this done by mistake so many times (and not once, I think, where it was a good idea), so I wanted to make a clear statement.Wallack
Yep, I think "evil" is about right... consider the case of null pointer exception thrown somewhere from a large body of code. The message is vanilla, without the stack trace you're left with "something was null somewhere". NOT good when production is dead; and you've NO minutes or less to work out the flamin' problem is, and dismiss or rectify it... Good exception handling is worth it's weight in gold.Minus
Is that true for Java as well ... "throw" vs. "throw ex"?Bistre
What happens in the situation where your logging code throws an exception?Twowheeler
@Jason, see this question. In Java, throw ex does not restart the stacktrace.Levirate
@Minus I've discovered that issue can be partially mitigated by setting VS to break on all exceptions, not just uncaught ones.Thickness
Of course, it could be that clearing the call stack might be exactly what the original programmer intended. It probably wasn't, but it might be so.Cirrhosis
Best way to "clean up" Compiler warnings complaining about unused ex variable?Windermere
@blacai simply don't add the "ex"Matthei
(Exception ex) There's NO INSTANTIATION here in contrast to what some have asserted. An Exception object is being created anyway. If you're merely going to throw, then there's no need for defining the Exception object with a variable. The variable is never used in this case, hence the Visual Studio warning. It's just like anywhere else in your code where you'd have a variable definition but no assignment.Lechery
F
146

Don't do this,

try 
{
...
}
catch(Exception ex)
{
   throw ex;
}

You'll lose the stack trace information...

Either do,

try { ... }
catch { throw; }

OR

try { ... }
catch (Exception ex)
{
    throw new Exception("My Custom Error Message", ex);
}

One of the reason you might want to rethrow is if you're handling different exceptions, for e.g.

try
{
   ...
}
catch(SQLException sex)
{
   //Do Custom Logging 
   //Don't throw exception - swallow it here
}
catch(OtherException oex)
{
   //Do something else
   throw new WrappedException("Other Exception occured");
}
catch
{
   System.Diagnostics.Debug.WriteLine("Eeep! an error, not to worry, will be handled higher up the call stack");
   throw; //Chuck everything else back up the stack
}
Flunky answered 19/5, 2009 at 8:3 Comment(14)
Why not just leave catch { throw } out altogether?Abstracted
added an example as to why, but yeah, in that contrived case, you could leave it out.Flunky
there's still value in leaving catch {throw; } at the bottom of a list of specific exception type catch's on the grounds it proves the author considered the case, though a comment might equally suffice. Not guessing when you read code is a good thing.Choking
Eoin, THANK YOU for the succinct (and now complete) example... This is IMHO exactly what the textbook should say at the start of the exception handling chapter... the rest of guff can wait, but that's the guts of the issue in a tea cup. Cheers. Keith.Minus
For some reason, the name of the SQLException bothers me.Yamen
That catch (Exception) { throw new Exception(...) } is something you should never, ever, ever do, simply because you're obfuscating the exception information and making exception filtering further up the call stack unnecessarily difficult. The only time you should catch one type of exception and throw another is when you are implementing an abstraction layer and you need to transform a provider-specific exception type (e.g. SqlException versus XmlException) into a more generic one (e.g. DataLoadingException).Updo
What if an ArgumentNullException is thrown somewhere deep in code that your class uses, and the only reason it is thrown is because the client passed a null argument into YOUR code. Wouldn't you want to reset the stack trace in this case? I would have thought it would be clearer if the stack trace showed that the NullArgumentException was thrown from the method the client called directly (making it clear which argument was null), rather than some method embedded deep in your own code (which might lead the client to think that your code simply has a bug)...Cottager
@Cottager you should check that argument upfront, at the beginning of the method and throw the ArgumentNullException there (fail fast).Overmuch
But adding another check up front means that the argument would get checked twice, right? Once in your code, and once further down in the code that your method uses. I know these types of checks are inexpensive, but what's the point of checking it early on if you can just catch (and rethrow) the ArgumentNullException when another method checks and throws it?Cottager
I have a feeling that this code's WrappedException forgets the wrapping. Was it the author's intention to put the original exception in that constructor as InnerException?Matthei
Under MS convention, only two-letter acronyms should remain uppercase (IOException), longer acronyms should be PascalCased (SqlException). Unlike in Java (see SQLException). That's the reason probably why SQLException bothers you, @MichaelMyers.Heckman
It's not every day I run across on answer on SO that totally changes how I approach a certain task. Kudos for teaching about throw new Exception(customMessage, caughtException); Now I have the benefit of catching and throwing exceptions ad-hoc plus customizing the messaging behavior while keeping the original exception behavior in-tact :)Delastre
Also, it's common for examples to catch (Exception ex) but 99.99% of the time you never want to catch System.Exception.Broadfaced
The answer should be corrected 1.to pass inner exception to WrappedException and 2. Either not include last catch block at all or catch(Exception ex) and include ex.ToString() in example log WriteLineTeague
A
62

C# (before C# 6) doesn't support CIL "filtered exceptions", which VB does, so in C# 1-5 one reason for re-throwing an exception is that you don't have enough information at the time of catch() to determine whether you wanted to actually catch the exception.

For example, in VB you can do

Try
 ..
Catch Ex As MyException When Ex.ErrorCode = 123
 .. 
End Try

...which would not handle MyExceptions with different ErrorCode values. In C# prior to v6, you would have to catch and re-throw the MyException if the ErrorCode was not 123:

try 
{
   ...
}
catch(MyException ex)
{
    if (ex.ErrorCode != 123) throw;
    ...
}

Since C# 6.0 you can filter just like with VB:

try 
{
  // Do stuff
} 
catch (Exception e) when (e.ErrorCode == 123456) // filter
{
  // Handle, other exceptions will be left alone and bubble up
}
Ailsa answered 19/5, 2009 at 8:20 Comment(3)
Dave, but (in java at least) you wouldn't throw a "generic" MyException, you'd define a SPECIFIC exception type and throw it, allowing it to be differentiated-by-type in the catch block... But yes, if your not the architect of the exception (I'm thinking JDBC's SQLException (Java again) here, which is disgustingly generic, and exposes getErrorCode() method... Hmmm... You've got a point, it's just that I think there's a better way to do it, where possible. Cheers Mate. I appreciate your time, a lot. Keith.Minus
Well, the question is "Why catch and rethrow Exception in C#?", and this is an answer. =] ...and even with specialized exceptions, Exception Filters make sense: consider the case where you are, let's say, handling a SqlTimeoutException and a SqlConnectionResetException, which are both SqlException. Exception Filters let you catch an SqlException only when it's one of these two, so instead of cluttering your try/catch with identical handling for these two, you could "catch SqlException ex when ex is SqlTimeoutException Or ex is SqlConnectionResetException". (I'm not Dave btw)Ailsa
Filtered exceptions are coming in C# 6!Koy
O
19

My main reason for having code like:

try
{
    //Some code
}
catch (Exception e)
{
    throw;
}

is so I can have a breakpoint in the catch, that has an instantiated exception object. I do this a lot while developing/debugging. Of course, the compiler gives me a warning on all the unused e's, and ideally they should be removed before a release build.

They are nice during debugging though.

Overwrite answered 18/9, 2009 at 9:50 Comment(4)
Yeah, I'll pay that one, but yes, you wouldn't want to see that in published code... ergo: I would be ashamed to publish it ;-)Minus
Actually, this isn't necessary -- in Visual Studio you can set the debugger to break when an exception is thrown and it brings up the exception details in an inspector window for you.Updo
If you want to use some code ONLY during debugging, use #if DEBUG ... #endif , and you don't need to remove these linesTeague
Ya, I've done that a few times myself. Every now and then one will escape to a release. @Updo The problem with Visual Studio's break on exception is, sometimes the exception I want isn't the only one (or even only one of its type) being thrown. Still don't know of a break point condition with "break if skipped by exception". Till then, this will remain useful. Michael Freidgeim: #if DEBUG around BOTH the try { and } catch () {...} is a bit messy and, frankly, makes me queasy... The pre-processor is, generally speaking, not my friend.Lilylivered
I
14

A valid reason for rethrowing exceptions can be that you want to add information to the exception, or perhaps wrap the original exception in one of your own making:

public static string SerializeDTO(DTO dto) {
  try {
      XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
      StringWriter sWriter = new StringWriter();
      xmlSer.Serialize(sWriter, dto);
      return sWriter.ToString();
  }
  catch(Exception ex) {
    string message = 
      String.Format("Something went wrong serializing DTO {0}", DTO);
    throw new MyLibraryException(message, ex);
  }
}
Inclusive answered 19/5, 2009 at 8:3 Comment(1)
Thanx, yep exception wrapping (especially chained) is perfectly sane... what is not sane is catching an exception just so you can chuck away the stack trace, or worse, eat it.Minus
P
11

You don't want to throw ex - as this will lose the call stack. See Exception Handling (MSDN).

And yes, the try...catch is doing nothing useful (apart from lose the call stack - so it's actually worse - unless for some reason you didn't want to expose this information).

Phosphoprotein answered 19/5, 2009 at 8:2 Comment(1)
You don't lose the entire call stack when you use throw ex, you just lose the part of the call stack from the point where the exception occurred higher up its call stack. But you retain the call stack from the method that threw the exception down to where the client called it. There actually might be use cases where you'd use that, or else the good people at Microsoft wouldn't have allowed it. That said, I haven't used it. Another issue to remember is that throwing exceptions is expensive. Only do it for a very justifiable reason. Logging I would think would be justifiable, etc.Lechery
U
10

Isn't this exactly equivalent to not handling exceptions at all?

Not exactly, it isn't the same. It resets the exception's stacktrace. Though I agree that this probably is a mistake, and thus an example of bad code.

Unaccountedfor answered 19/5, 2009 at 8:11 Comment(0)
S
6

This can be useful when your programming functions for a library or dll.

This rethrow structure can be used to purposefully reset the call stack so that instead of seeing the exception thrown from an individual function inside the function, you get the exception from the function itself.

I think this is just used so that the thrown exceptions are cleaner and don't go into the "roots" of the library.

Smelt answered 27/5, 2018 at 15:35 Comment(0)
C
5

A point that people haven't mentioned is that while .NET languages don't really make a proper distinction, the question of whether one should take action when an exception occurs, and whether one will resolve it, are actually distinct questions. There are many cases where one should take action based upon exceptions one has no hope of resolving, and there are some cases where all that is necessary to "resolve" an exception is to unwind the stack to a certain point--no further action required.

Because of the common wisdom that one should only "catch" things one can "handle", a lot of code which should take action when exceptions occur, doesn't. For example, a lot of code will acquire a lock, put the guarded object "temporarily" into a state which violates its invariants, then put it object into a legitimate state, and then release the lock back before anyone else can see the object. If an exception occurs while the object is in a dangerously-invalid state, common practice is to release the lock with the object still in that state. A much better pattern would be to have an exception that occurs while the object is in a "dangerous" condition expressly invalidate the lock so any future attempt to acquire it will immediately fail. Consistent use of such a pattern would greatly improve the safety of so-called "Pokemon" exception handling, which IMHO gets a bad reputation primarily because of code which allows exceptions to percolate up without taking appropriate action first.

In most .NET languages, the only way for code to take action based upon an exception is to catch it (even though it knows it's not going to resolve the exception), perform the action in question and then re-throw). Another possible approach if code doesn't care about what exception is thrown is to use an ok flag with a try/finally block; set the ok flag to false before the block, and to true before the block exits, and before any return that's within the block. Then, within finally, assume that if ok isn't set, an exception must have occurred. Such an approach is semantically better than a catch/throw, but is ugly and is less maintainable than it should be.

Ciceronian answered 14/10, 2013 at 16:56 Comment(0)
A
4

While many of the other answers provide good examples of why you might want to catch an rethrow an exception, no one seems to have mentioned a 'finally' scenario.

An example of this is where you have a method in which you set the cursor (for example to a wait cursor), the method has several exit points (e.g. if () return;) and you want to ensure the cursor is reset at the end of the method.

To do this you can wrap all of the code in a try/catch/finally. In the finally set the cursor back to the right cursor. So that you don't bury any valid exceptions, rethrow it in the catch.

try
{
    Cursor.Current = Cursors.WaitCursor;
    // Test something
    if (testResult) return;
    // Do something else
}
catch
{
    throw;
}
finally
{
     Cursor.Current = Cursors.Default;
}
Allyce answered 9/8, 2016 at 11:47 Comment(1)
Was catch a mandatory part of try...finally historically, or does it play a functional role in this example? - I just double-checked, and I'm able to use try {} finally {} without the catch block at all.Holloway
N
3

It depends what you are doing in the catch block, and if you are wanting to pass the error on to the calling code or not.

You might say Catch io.FileNotFoundExeption ex and then use an alternative file path or some such, but still throw the error on.

Also doing Throw instead of Throw Ex allows you to keep the full stack trace. Throw ex restarts the stack trace from the throw statement (I hope that makes sense).

Nadianadine answered 19/5, 2009 at 8:4 Comment(0)
E
3

One possible reason to catch-throw is to disable any exception filters deeper up the stack from filtering down (random old link). But of course, if that was the intention, there would be a comment there saying so.

Enriquetaenriquez answered 30/7, 2009 at 15:12 Comment(2)
I didn't get what you where on about until I read the link... and I'm still not exactly sure what you're on about... me being totally unfamiliar with VB.NET. I think it results in the sum being reported "inconsistent", right?... I'm a BIG fan of static methods.. apart from them being simple, there's less chance of inconsistency if you seperate the setting of attributes from the code which does the actual work. The stack is "self cleansing".Minus
People expect that when they write "try { Foo(); } finally { Bar(); }" that nothing runs between Foo and Bar. But this is not true; if your caller added an exception filter, and there is no intervening 'catch', and Foo() throws, then some other random code from your caller will run before your finally (Bar) runs. This is very bad if you've broken invariants or elevated security, expecting that they'll be 'immediately' restored to normal by the finally and no other code will see the temporary change.Enriquetaenriquez
Y
2

In the example in the code you have posted there is, in fact, no point in catching the exception as there is nothing done on the catch it is just re-thown, in fact it does more harm than good as the call stack is lost.

You would, however catch an exception to do some logic (for example closing sql connection of file lock, or just some logging) in the event of an exception the throw it back to the calling code to deal with. This would be more common in a business layer than front end code as you may want the coder implementing your business layer to handle the exception.

To re-iterate though the There is NO point in catching the exception in the example you posted. DON'T do it like that!

Yttriferous answered 19/5, 2009 at 8:19 Comment(0)
C
1

Sorry, but many examples as "improved design" still smell horribly or can be extremely misleading. Having try { } catch { log; throw } is just utterly pointless. Exception logging should be done in central place inside the application. exceptions bubble up the stacktrace anyway, why not log them somewhere up and close to the borders of the system?

Caution should be used when you serialize your context (i.e. DTO in one given example) just into the log message. It can easily contain sensitive information one might not want to reach the hands of all the people who can access the log files. And if you don't add any new information to the exception, I really don't see the point of exception wrapping. Good old Java has some point for that, it requires caller to know what kind of exceptions one should expect then calling the code. Since you don't have this in .NET, wrapping doesn't do any good on at least 80% of the cases I've seen.

Cychosz answered 16/9, 2009 at 7:22 Comment(4)
Thank you for your thought Joe. In Java (and C#, I suppose) I would love to see a class-level annotation @FaultBoundary which forces ALL exceptions (including unchecked exception-types) to be caught-or-declared-to-be-thrown. I would use this annotation on public interfaces of each architectural layer. So the @FaultBoundary ThingDAO interface would not be able to leak implementation details such as SQLExceptions, NPE's, or AIOB's. Instead "causal" stacktrace would be logged and a DAOSystemException would be thrown... I define System exception as "permanently fatal".Minus
There are plenty of reasons to catch, log, then rethrow. Specifically if the method with the catch log has information you lose once you're out of the method. The error may be handled later but not logged, and you've lost information about defects in the system.Serviceberry
This is where the Data property of the Exception class is handy -- capturing all that local information for generic logging. This article originally brought it to my attention: blog.abodit.com/2010/03/…Ballet
Sonar will now flag "meaningless" catch/log/(re)throw. But has a message like 'avoid doing this, OR add some extra context to the log message". So I think sometimes it is somewhat meaningless, but other times..if you add-some-extra-info...it can be helpful.Nutriment
F
1

In addition to what the others have said, see my answer to a related question which shows that catching and rethrowing is not a no-op (it's in VB, but some of the code could be C# invoked from VB).

Fulbright answered 22/9, 2009 at 19:53 Comment(4)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewHangover
@HamzaLH, I agree that it is not a well written answer, but it has information, different to other answers and positive votes. So I don’t understand, why you suggest to delete it? “Short answers that are on topic and give a solution are still answers.” From meta.stackexchange.com/questions/226258/…Teague
this is link-only answerHangover
1. Link-only answers should be change to comments, not deleted. 2. It’s a reference to other SO question, not to external site, which considered less likely to be broken over time. 3. It has some extra description, which make it not “link only” - see meta.stackexchange.com/questions/225370/…Teague
T
1

Most of answers talking about scenario catch-log-rethrow.

Instead of writing it in your code consider to use AOP, in particular Postsharp.Diagnostic.Toolkit with OnExceptionOptions IncludeParameterValue and IncludeThisArgument

Teague answered 25/12, 2012 at 22:41 Comment(4)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewMonotony
@TonyDong, I agree that it is not a well written answer, but it has information, different to other answers and positive votes. So I don’t understand, why you suggest to delete it? BTW, the link 5 years later is still valid. “Short answers that are on topic and give a solution are still answers.” From meta.stackexchange.com/questions/226258/…Teague
Stackoverflow only has this suggestion.Monotony
@TonyDong, if the answer is not absolutely useless, you should choose “Looks OK”Teague
T
1

Rethrowing exceptions via throw is useful when you don't have a particular code to handle current exceptions, or in cases when you have a logic to handle specific error cases but want to skip all others.

Example:

string numberText = "";
try
{
    Console.Write("Enter an integer: ");
    numberText = Console.ReadLine();
    var result = int.Parse(numberText);

    Console.WriteLine("You entered {0}", result);
}
catch (FormatException)
{
    if (numberText.ToLowerInvariant() == "nothing")
    {
        Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
    }
    else
    {
        throw;
    }
}    
finally
{
    Console.WriteLine("Freed some resources.");
}
Console.ReadKey();

However, there is also another way of doing this, using conditional clauses in catch blocks:

string numberText = "";
try
{
    Console.Write("Enter an integer: ");
    numberText = Console.ReadLine();
    var result = int.Parse(numberText);

    Console.WriteLine("You entered {0}", result);
}
catch (FormatException) when (numberText.ToLowerInvariant() == "nothing")
{
    Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
}    
finally
{
    Console.WriteLine("Freed some resources.");
}
Console.ReadKey();

This mechanism is more efficient than re-throwing an exception because of the .NET runtime doesn’t have to rebuild the exception object before re-throwing it.

Thrombus answered 9/12, 2019 at 17:8 Comment(0)
N
0

I upvoted eoin's answer.

I will add two more caveats (different from his answer)

try
{
   ...
}
catch(SQLException sqlex)
{
   /* you can optionally look at the ".Number" , but here I do not want to "leak" a database error details that talks about table-names, column-names, etc, etc */
   throw new UserFacingFriendlyException("There was a issue with the database operation", sqlex);
}
catch(ArithmeticException aex)
{    
   /* throw the exact same aex so my "handler" can deal with this specific exception type */
   throw;
}
  1. With a SQLException (or SqlException !! haha) ... you might not want the "inner real details" of that getting to the outside user. Thus you catch and wrap it as another exception. (this one may be part of eoin's original answer, but I am drawing attention to it)

or

2.

You have a "handler" (for a specific exception type)... somewhere in your upper layers.... that is looking for a specific exception (type).

If you had a

https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-6.0#exception-filters

or a custom "IActionFilter, IOrderedFilter" (below url)

https://learn.microsoft.com/en-us/aspnet/core/web-api/handle-errors?view=aspnetcore-6.0#use-exceptions-to-modify-the-response-1

and either of those was explicitly looking for the "ArithmeticException", then you would not want to "disturb it". .

In second ("IActionFilter, IOrderedFilter") URL article, m$ has named their example:

HttpResponseExceptionFilter : IActionFilter, IOrderedFilter

In my "catch ArithmeticException and throw" example (in this answer).... you might have written an explicit handler for it called:

ArithmeticExceptionFilter : IActionFilter, IOrderedFilter

to handle (specifically) an ArithmeticException.

.........

and if you "merge" the 2 things above.

UserFacingFriendlyException

I try to have my business logic always throw this exception.

because (drum roll :) )

I only defined 2

IActionFilter, IOrderedFilter

(1)

UserFacingFriendlyExceptionFilter : IActionFilter, IOrderedFilter

   // deal with UserFacingFriendlyExceptions ONLY. but "pass through" anything else that is not a UserFacingFriendlyException

and ~~just in case I missed anything

(2)

ExceptionFallThroughFilter  : IActionFilter, IOrderedFilter
    //(for anything that slipped by the UserFacingFriendlyExceptionFilter)

This way... I am guaranteed of "no leakage" of internal exceptions.

Nutriment answered 23/8, 2023 at 19:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.