代码之家  ›  专栏  ›  技术社区  ›  uriDium

使用内部异常或创建基异常的派生类型

  •  0
  • uriDium  · 技术社区  · 3 年前

    如果有一个方法调用了许多其他方法,并且它们都可以抛出从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(){ }
    }
    
    1 回复  |  直到 3 年前
        1
  •  0
  •   Heinzi    3 年前

    这只是取决于你的来电者是否可能 需要 捕捉异常时的详细程度。

    我的建议是首先实施备选方案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向后兼容,因为DoSomethingMissingArgException DoSomethingException。您还可以根据需要添加更多的异常子类 同时保持向后兼容 .
    • 您只有在方法DoSomething中才有特定于DoSometing的异常逻辑,而不是分散在您的辅助方法中,这些方法可以使用“自然”BCL执行选项。