首页 > 解决方案 > 使用内部异常或创建基本异常的派生类型

问题描述

如果有一个方法调用了许多其他方法并且它们都可以抛出从 ArgumentExceptions 到 EndOfStreamExceptions 的各种异常,最好做一个 catch all 并将其包装在您自己的异常中,然后设置内部异常,或者创建一个基类异常和抛出派生类型。如果抛出违反尽可能重用 BCL 异常的建议的派生类型。所以例如

public void A()
{
    if (someCondition)
    {
        throw new ArgumentException()
    }
}

public void B()
{
    if (anotherCondition)
    {
        throw new InvalidOperation()
    }
}

public void C()
{
    // Throws format exception
    int.Parse(x);
}

public void DoSomething()
{
    try
    {
        A();
        B();
        C();
    }
    catch(Exception ex)
    {
        throw new DoSomethingException("Could not complete DoSomthing"){ InnerException = ex};
    }
}

或者做类似的事情会更好吗

public void DoSomething()
{
    A();
    B();
    C();
    D();
}

public void A()
{
    if (someCondition)
    {
        throw new DoSomethingMissingArg()
    }
}

public void B()
{
    if (anotherCondition)
    {
        throw new DoSomethingCannotStart()
    }
}

public void C()
{
    // Throws format exception
    if (!int.TryParse(x))
    {
        throw new DoSomethingFormatException("x must be in y format");
    }
}

public class DoSomethingException: Exception
{

}

public class DoSomethingMissingArg: DoSomethingException
{
    public DoSomethingMissingArg(){ }
}

public class DoSomethingCannotStart: DoSomethingException
{
    public DoSomethingCannotStart(){ }
}

public class DoSomethingFormatException: DoSomethingException
{
    public DoSomethingFormatException(){ }
}

标签: c#exception

解决方案


这仅取决于您的调用者在捕获异常时是否可能需要该级别的详细信息。

我的建议是首先实施选项 1,然后,如果需要更多详细信息,请切换到以下选项 3:

public void A()
{
    if (someCondition)
    {
        throw new ArgumentException()
    }
}

...    

public void DoSomething()
{
    try
    {
        A();
    }
    catch(ArgumentException ex)
    {
        throw new DoSomethingMissingArgException() { InnerException = ex };
    }

    try
    {
        B();
        C();
    }
    catch(Exception ex)
    {
        throw new DoSomethingException("Could not complete DoSomthing"){ InnerException = ex};
    }
}

选项 3 具有以下优点:

  • 它向后兼容选项 1,因为 DoSomethingMissingArgExceptionDoSomethingException。并且您可以根据需要添加更多异常子类,同时保持向后兼容
  • 您仅在方法 DoSomething 中具有特定于 DoSomething 的异常逻辑,而不是分散在您的辅助方法周围,这些方法可以使用“自然”BCL 执行。

推荐阅读