从catch语句引发自定义异常是一种好习惯吗?

时间:2018-09-04 12:12:20

标签: c# exception custom-exceptions nested-exceptions

我有运行测试的命令行工具。有一个测试运行程序类,它在执行测试之前进行一些准备,然后运行测试并生成报告。 如果我的类捕获到异常并将新的自定义异常抛出到上层,然后上层也将其抛出到上层(直到View类将显示/记录该异常),可以吗?

class Program
{
    static void Main(string[] args)
    {
        testRunner = new TestRunner();

        try
        {
            testRunner.RunTest();
            testRunner.GetReport();
        }
        catch (TestRunnerException ex)
        {
            Print(ex);  // prints nicely two levels of exceptions for user
            Log(ex);    // writes to file all levels of exceptions
        }
    }
}

class TestRunner
{
    void RunTest()
    {
        // run test here
    }

    TestReport GetTestReport()
    {
        try
        {
            return testReporter.GenerateReport();
        }
        catch (Exception ex)
        {
           throw new TestRunnerException("Failed to generate report.", ex);
        }
    }
}


class TestReporter
{
    TestReport GenerateReport()
    {
        try
        {
            // create report here
        }
        catch (Exception ex)
        {
            throw new ReportException($"Test '{testName}' missing data.", ex)
        }
    }
}

1 个答案:

答案 0 :(得分:1)

不是来自catch抛出自定义异常,而是捕获了所有的异常行为,这是一种不好的做法;想象一下:

  TestReport GetTestReport() {
    // throws NullReferenceException (yes, GenerateReport() has a bug)
    return testReporter.GenerateReport(); 
  }
  catch (Exception ex) {
    // Bad Practice: here we hide hideous NullReferenceException, 
    // but throw innocent TestRunnerException
    throw new TestRunnerException("Failed to generate report.", ex);
  }

  ...

  try { 
    GetTestReport();
  }
  catch (TestRunnerException ex) {
    // Nothing serious: Tests report fails, let's do nothing
    // Under the hood: the routine went very wrong  - 
    // NullReferenceException - in GenerateReport(); 
    ;
  }

我建议在catch中使用 specific 例外:

  TestReport GetTestReport() {
    // throws NullReferenceException 
    return testReporter.GenerateReport(); 
  }
  catch (NotAuthorizedException ex) {
    // We are not allowed to run tests only, nothing serious
    throw new TestRunnerException("Failed to generate report. Not authorized", ex);
  }

  ...

  try { 
    GetTestReport();
  }
  catch (TestRunnerException ex) {
    // Nothing serious: Tests report fails, let's do nothing
    ;
  }