捕获基础异常但不捕获子异常

Catching base but not sub exceptions

我正在编写一个 HttpHandler,作为我内部设计的一部分,我抛出不同的异常并在顶层捕获它们以确定将请求设置为什么状态代码。

即 ArgumentException 触发错误请求
AuthenticationException 触发 Unauthorised
OracleException 触发 InternalServerError
等等

我发现的问题是我使用 InvalidOperationException 来触发 NotFound,但是我的代码中的一个错误让我意识到,当然,一些系统异常继承自这些基本系统异常,这会导致意外响应.

即我发现 ObjectDisposedException 继承自 InvalidOperationException,这意味着响应 returns 是 404 而不是 500.

有没有办法只捕获基本异常?

我发现 this thread 这表明我可以进行过滤并重新抛出,但这似乎很老套。

我是否最好只创建自己的异常类型来避免所有这些麻烦?

如果您只想将 HTTP 结果代码(可能还有错误消息行)传递给客户端,那么我建议您创建一个 单个 自定义异常:

public class MyCustomException : Exception { // Or maybe InvalidOperationException
    public int StatusCode {get;set;}
    public string Status {get;set;}
}

等等

据我所知,没有办法捕获异常但不捕获继承的异常。问题是你认为基本异常比继承异常更具体,这与它们的工作方式相反(继承异常应该是它们父类的更具体的子集,所以从概念上讲,如果你能处理您应该能够处理继承异常的父级)。

你的选择基本上是:

  1. 创建您自己的异常类型并只捕获它。如果您的异常属于 InvalidOperationException 的定义,那么您可以继承它。然后你就可以专门抓住你的了。
  2. 如果不是您想要的,请接住、检查并重新投掷。我通常会尽量避免这种技术,但如果异常类型过于通用,有时则需要这种技术。例如

    catch (InvalidOperationException ex) { 
       if (ex.GetType() != typeof(InvalidOperationException)) throw;
       /* Do stuff */
    }
    

不可能只捕获基本异常。

在这种情况下,最好创建自定义异常,而不是使用系统的异常类型。

public class HttpErrorException : Exception
{
    public HttpStatusCode StatusCode { get; private set; }
    public HttpErrorException(HttpStatusCode code, string message)
        : base(message)
    {
        this.StatusCode = code;
    }
}

throw new HttpErrorException(400, "You sent a bad request!");

如果初衷是混淆 HTTP 状态代码,而不是使用它们的文本名称,则可以创建工厂方法。

public class HttpErrorException : Exception
{
    public HttpStatusCode StatusCode { get; private set; }

    private HttpErrorException(HttpStatusCode code, string message)
        : base(message)
    {
        this.StatusCode = code;
    }

    public static HttpErrorException BadRequest(string message)
    {
        return new HttpErrorException(400, message);
    }

    public static HttpErrorException InternalServerError(string message)
    {
        return new HttpErrorException(500, message);
    }
    // etc
}

throw HttpErrorException.BadRequest("You made a bad request!");