Является ли хорошей практикой выбрасывать пользовательское исключение из оператора catch?

У меня есть инструмент командной строки, который запускает тесты. Существует класс бегуна теста, который выполняет некоторую подготовку перед выполнением теста, а затем запускает тест и составляет отчет. Можно ли, если мои классы перехватят исключение и сгенерируют новое пользовательское исключение на верхний уровень, а затем верхний уровень также сгенерирует его на верхний уровень (до класса 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 ответ

Это не выбрасывает пользовательское исключение из 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:

  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
    ;
  }
Другие вопросы по тегам