C # try..catch - перенаправление потока обработки ошибок от одного улова к следующему

У меня есть блок try..catch, который выглядит следующим образом:

try
{
    ...
}
catch (IOException ioEx)
{
    ...
}
catch (Exception ex)
{
    ... 
}

Я бы хотел обработать только один определенный вид IOException , а именно нарушение совместного использования (Win32 0x20). Другие исключения IOExceptions и все другие потомки Exception должны обрабатываться, как правило, с помощью второго универсального улова.

Как только я узнаю, что IOException не является нарушением совместного использования, как я могу чисто перенаправить поток обработки ошибок на общий улов ? Если я повторно выброшу в catch (IOException) , второй catch не будет активирован. Я знаю, что могу вложить try..catches, но есть ли более чистый способ?

РЕДАКТИРОВАТЬ: При разложении логики обработчика

Факторинг повторяющегося кода в методах наверняка сработает, но я заметил, что в целом, когда вы используете факторизованные методы для обработки исключений это имеет тенденцию иметь тонкие проблемы.

Прежде всего, предложение catch имеет прямой доступ ко всем локальным переменным до исключения. Но когда вы «передаете» обработку исключений другому методу, вы должны передать ему состояние. И когда вы меняете код, меняется и сигнатура метода обработчика, что может быть проблемой ремонтопригодности в более сложных сценариях.

Другая проблема заключается в том, что поток программы может быть скрыт. Например, если метод обработчика в конечном итоге вызывает исключение, компилятор C # и анализаторы кода, такие как Resharper, не видят его:

    private void Foo()
    {
        string a = null;

        try
        {
            a = Path.GetDirectoryName(a);
            System.Diagnostics.Debug.Print(a);
        }
        catch (Exception ex)
        {                
            HandleException(ex, a); //Note that we have to pass the "a"
            System.Diagnostics.Debug.Print(
                "We never get here and it's not obvious" + 
                "until you read and understand HandleException"
            );
            ...!
        }
    }

    static void HandleException(Exception ex, string a)
    {
        if (a != null)
            System.Diagnostics.Debug.Print("[a] was not null");
        throw (ex); //Rethrow so that the application-level handler catches and logs it
    }

VS

    private void Bar()
    {
        string a = null;

        try
        {
            a = System.IO.Path.GetDirectoryName(a);
            System.Diagnostics.Debug.Print(a);
        }
        catch (Exception ex)
        {                
            if (a != null)
                System.Diagnostics.Debug.Print("[a] was not null");
            throw; //Rethrow so that the application-level handler catches and logs it
            System.Diagnostics.Debug.Print(
                "We never get here also, but now " + 
                "it's obvious and the compiler complains"
            );
            ...!
        }
    }

Если я хочу избежать подобных (незначительных) проблем, то кажется, что Как отметил Хэнк, нет более чистого способа, чем вложение блоков try..catch.

5
задан Boris B. 27 May 2011 в 19:25
поделиться