确定异常类型的更好方法(性能)是什么?

时间:2015-02-02 14:45:30

标签: c# error-handling

我已从OnException覆盖了ExceptionFilterAttribute

    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)。其他一些方式?

3 个答案:

答案 0 :(得分:1)

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

第二种方法的结构更好,但可以改进其实现。像这样:

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

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

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

答案 1 :(得分:1)

这实际上取决于你想要实现的目标,但我肯定不会抛出并捕获异常只是为了确定类型。除了第二种方法,您可能还需要考虑使用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继承的任何其他异常。

答案 2 :(得分:1)

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

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

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

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

您可以获取该类的名称并在开关中使用:

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对于所有异常都将为true。该开关仅与context.Exception.GetType() == typeof(Exception)完全匹配。