C#try..catch - 将错误处理流从一个catch重定向到下一个catch

Bor*_* B. 5 c# try-catch

我有一个try..catch块,看起来像这样:

try
{
    ...
}
catch (IOException ioEx)
{
    ...
}
catch (Exception ex)
{
    ... 
}
Run Code Online (Sandbox Code Playgroud)

我想处理某种IOException,即共享冲突(Win32 0x20).其他IOExceptions和所有其他Exception后代应该通过第二个catch-all catch来处理.

一旦我知道IOException不是共享冲突,我怎样才能将错误处理流程干净地重定向到一般catch?如果我在catch (IOException)第二次捕获中重新抛出则不会调用.我知道我可以嵌套try..catches但是有更清洁的方法吗?

编辑:关于分解处理程序逻辑

在方法中考虑重复的代码肯定会起作用,但我注意到,一般来说,当你使用因式方法进行异常处理时,它往往会产生微妙的问题.

首先,一个catch子句可以在异常之前直接访问所有局部变量.但是当你将异常处理"外包"到另一种方法时,你必须将状态传递给它.当您更改代码时,处理程序方法的签名也会发生更改,这可能是更复杂方案中的可维护性问题.

另一个问题是程序流程可能会模糊不清.例如,如果处理程序方法最终重新抛出异常,那么像Resharper这样的C#编译器和代码分析器看不到它:

    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
    }
Run Code Online (Sandbox Code Playgroud)

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"
            );
            ...!
        }
    }
Run Code Online (Sandbox Code Playgroud)

如果我想避免这些(次要的)问题,那么似乎没有比嵌套try..catch块更清洁的方法,正如Hank指出的那样.

Bor*_* B. -1

C# 6 引入了when 异常过滤器,可以更好地控制应调用哪个 catch 块。接受when一个有权访问异常对象的表达式并返回一个布尔值。如果表达式产生false,则跳过该处理程序并考虑下一个处理程序:

        try
        {
            var responseText = await streamTask;
            return responseText;
        }
        catch (HttpRequestException e) when (e.Message.Contains("301"))
        {
            return "Site Moved";
        }
        catch (HttpRequestException e) when (e.Message.Contains("404"))
        {
            return "Page Not Found";
        }
        catch (HttpRequestException e)
        {
            return e.Message;
        }
Run Code Online (Sandbox Code Playgroud)