Why catch and rethrow an exception in C#?

前端 未结 17 621
遥遥无期
遥遥无期 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:10

    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.

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

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

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

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

    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!

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

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

    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.

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