Why catch and rethrow an exception in C#?

前端 未结 17 642
遥遥无期
遥遥无期 2020-11-22 14:56

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

The article includes this piece of code:

public static string Se         


        
相关标签:
17条回答
  • 2020-11-22 15:05

    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;
    }
    
    0 讨论(0)
  • 2020-11-22 15:06

    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;
    }
    
    0 讨论(0)
  • 2020-11-22 15:06

    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
    }
    
    0 讨论(0)
  • 2020-11-22 15:06

    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.

    0 讨论(0)
  • 2020-11-22 15:06

    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.

    0 讨论(0)
  • 2020-11-22 15:09

    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).

    0 讨论(0)
提交回复
热议问题