返回异常对象而不是抛出它们有原因吗?

这是每周系列帖子的一部分,重点介绍技术爱好者常见问题,并由Stack Exchange的用户回答,这是一个由 100 多个问答网站组成的免费、社区驱动的网络。

stakx提问:此问题适用于任何支持异常处理的 OO 编程语言,仅以 C#为例。异常通常在代码无法立即处理的问题发生时引发,然后在不同位置(通常是外部堆栈帧)的catch子句中捕获。问题是:是否存在任何合法情况,异常不被抛出和捕获,而是从方法中简单返回,然后作为错误对象传递?此问题源于.NET 4 的System.IObserver.OnError方法,该方法建议将异常作为错误对象传递。

以验证为例,区分错误对象类型IValidationError和单独的异常类型ValidationException来报告意外错误:

partial interface IValidationError { }

abstract partial class ValidationException : System.Exception
{
    public abstract IValidationError[] ValidationErrors { get; }
}

然后思考能否简化为:

partial class ValidationError : System.Exception { } 

partial interface IFoo { } 

partial interface IFooBuilder
{
    bool IsValid(out ValidationError[] validationErrors);
    IFoo Build(); 
}

讨论这两种不同方法的优缺点。

什么是异常?

Mathew Foscarini回答(18 票):如果未抛出则不是异常,是从异常类派生的对象,但不遵循异常行为,称为异常只是语义上的,不抛出也没问题,不抛出异常就像内部函数捕获并阻止其传播。函数返回异常对象是合法的,如异常工厂、包含先前错误的上下文对象、保留先前捕获异常的函数、第三方 API 创建的内部类型异常等。抛出异常就像“去监狱,不要经过 Go!”,与错误报告或停止错误无关,重要的是理解异常的真正价值在于try/catch模式,而不是异常对象的实例化,不要混淆异常的使用和它所代表的错误状态。

例如

Philipp回答(42 票):返回异常而不是抛出异常在有辅助方法分析情况并返回适当异常然后由调用者抛出时具有语义意义(可称为“异常工厂”),抛出异常表示分析出错,返回异常表示错误类型分析成功,如将 HTTP 响应代码转换为异常的函数:

Exception analyzeHttpError(int errorCode) {
    if (errorCode < 400) {
         throw new NotAnErrorException();
    }
    switch (errorCode) {
        case 403:
             return new ForbiddenException();
        case 404:
             return new NotFoundException();
        case 500:
             return new InternalServerErrorException();
        …
        default:
             throw new UnknownHttpErrorCodeException(errorCode);
     }
}

注意抛出异常表示方法使用错误或内部错误,返回异常表示错误代码识别成功。更多答案可在原始帖子查看,更多类似问答可在Programmers查看,欢迎登录并提出自己的问题[http://programmers.stackexcha...]。

阅读 6
0 条评论