哪种方法(为了性能)确定异常类型更好?

Which is the better way (for performance) to determine the exception type?

我已经从 ExceptionFilterAttribute 覆盖了 OnException

    public override void OnException(HttpActionExecutedContext context) {

        base.OnException(context);
    }

当抛出错误并将异常作为参数传递时调用此函数:- context.Exception

确定错误类型的最佳性能方法是:

1).投掷和接球

    //create a new response that will be sent to the API consumer
    var response = new System.Net.Http.HttpResponseMessage();
    //throw the error that came through to catch it specifically
    try {
        throw context.Exception;
    }
    catch (System.IO.FileNotFoundException) {
        response.StatusCode = HttpStatusCode.NotFound;
    }
    catch (Exception) {
        response.StatusCode = HttpStatusCode.InternalServerError;
    }

2).获取类型

        //create a new response that will be sent to the API consumer
        var response = new System.Net.Http.HttpResponseMessage();

        //switch on the exception type
        if (context.Exception.GetType() == typeof(System.IO.FileNotFoundException)) {
            response.StatusCode = HttpStatusCode.NotFound;
        }
        else if (context.Exception.GetType() == typeof(Exception)) {
            response.StatusCode = HttpStatusCode.InternalServerError;
        }

3). 其他方式?

我怀疑(尽管尚未证实)第一种方法会破坏堆栈跟踪数据,或者以其他方式修改异常本身并丢失原始信息。即使碰巧它没有这样做,但出于性能和语义原因,它仍然不是很好。 throwing 很昂贵,调试时异常的来源变得稍微难以确定,并且它打破了从不使用异常进行逻辑流程的标准规则。

第二种方式的结构比较好,但是实现上还有待改进。像这样:

var response = new System.Net.Http.HttpResponseMessage();

if (context.Exception is System.IO.FileNotFoundException) {
    response.StatusCode = HttpStatusCode.NotFound;
}
else {
    response.StatusCode = HttpStatusCode.InternalServerError;
}

更新: 评论是正确的,对 Exception 类型的任何其他异常的运行时检查都会成功,因此不需要检查。只需检查特定的异常类型,然后默认为任何其他类型。

这真的取决于你想要实现什么,但我绝对不会为了确定类型而抛出和捕获异常。除了第二种方法,您可能还想考虑使用 is 运算符。这将更像抛出和捕获,因为它检查对象是否可以转换为类型,而 GetType 将获得异常的确切类型。

var response = new System.Net.Http.HttpResponseMessage();
if (context.Exception is System.IO.FileNotFoundException) 
{
    response.StatusCode = HttpStatusCode.NotFound;
}
else if (context.Exception is IOException) 
{
    response.StatusCode = HttpStatusCode.InternalServerError;
}

在上面的示例中,第一个 if 仅适用于 FileNotFoundException,第二个适用于属于或继承自 IOException 的任何其他异常。

三个。

抛出异常以捕获它意味着创建了一个全新的异常对象,因此这比需要的工作多得多。

第二种方法更好,但还可以改进。

您可以使用 is 运算符来检查对象的类型:

if (context.Exception is System.IO.FileNotFoundException)) {
  response.StatusCode = HttpStatusCode.NotFound;
} else if (context.Exception is Exception) {
  response.StatusCode = HttpStatusCode.InternalServerError;
}

您可以获得 class 的名称并在开关中使用:

switch (context.Exception.GetType().FullName) {
  case "System.IO.FileNotFoundException":
    response.StatusCode = HttpStatusCode.NotFound;
    break;
  case "Exception":
    response.StatusCode = HttpStatusCode.InternalServerError;
    break;
}

注意,不同的方法匹配的内容是有区别的。 is 运算符还将包括基类型(就像 catch(Exception) 一样),因此 context.Exception is Exception 对所有异常都为真。 switch 只会进行精确匹配,就像 context.Exception.GetType() == typeof(Exception).