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

问题描述 投票:0回答:7

我有一个 try..catch 块,如下所示:

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

我只想处理某种类型的

IOException
,即共享冲突(Win32 0x20)。其他 IOException 和所有其他
Exception
后代通常应由第二个 catch-all catch 处理。

一旦我知道 IOException 不是共享冲突,我怎样才能干净地将错误处理流程重定向到常规

catch
?如果我重新抛出
catch (IOException)
,第二个 catch 不会调用。我知道我可以嵌套尝试..捕获但是有更干净的方法吗?

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

在方法中分解重复的代码肯定会起作用,但我注意到,一般来说,当您使用分解方法进行异常处理时,它往往会出现微妙的问题。

首先,

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 块更干净的方法了,正如 Hank 指出的那样。

c# try-catch
7个回答
4
投票

只需将处理逻辑分解到一个单独的方法中即可。

try
{
    ...
}
catch (IOException ioEx)
{
    if (sharing violation)
       HandleSharingViolation();
    else 
       HandleNonsharingViolation();
}
catch (Exception ex)
{
       HandleNonsharingViolation();
}

或者自己测试异常情况

catch (Exception ex)
{
     if (ex is IOException && ex.IsSharingViolation()
       HandleSharingViolation();
     else
       HandleNonsharingViolation();
}

3
投票

不,你必须筑巢。

一旦进入其中一个 catch 块,该“try”就被视为已处理。

我认为这可能很有意义,“共享违规”听起来像是一种特殊情况,可能并不像您想象的那样与其他情况紧密耦合。如果您使用嵌套 try-catch,特殊情况的 try 块是否必须包围exact相同的代码?当然,它是一个可以重构为单独方法的候选者。


0
投票

创建方法来处理异常,将异常传递给该方法,根据类型以您想要的方式处理异常。在这两个块中调用这些方法。


0
投票

使用嵌套的 try catch 块。

try
{
    try
    {
    }
    catch (IOException ioEx)
    {
        if (....)
        else
           throw;
    }
}
catch
{
}

0
投票

“终于”呢?

一旦知道 IOException 不存在共享冲突,您就可以首先在 IOException 块中设置一个“变量”。然后,在您的finally块中,如果设置了该“变量”,您就可以继续执行您需要执行的操作。

以下暗示。测试并确认。

        bool booleanValue = false;
        try
        {
            test1(); // this would thro IOException

        }
        catch (IOException e)
        {
            booleanValue = true; // whatever you need to do next
        }
        finally
        {
            if (booleanValue)
            {
                Console.WriteLine("Here");
            }
        }

0
投票

尝试这个嵌套块

尝试
{

}

catch(异常ioex)
{
尝试
{

}
捕获(异常前)
{

}
}


-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;
        }
© www.soinside.com 2019 - 2024. All rights reserved.