检查异常类型性能

时间:2016-12-14 10:50:43

标签: c# performance exception exception-handling

我有一个方法可以检查传入的异常并返回一个bool值。

目前我的实施就像这样

private bool ExceptionShouldNotify(Exception e)
{
    return
    e is FirstCustomException  ||
    e is SecondCustomException ||
    e is ThirdCustomException  ||
    e is FourthCustomException ||
    e is FifthCustomException  ||
    e is SixthCustomException  ||
    e is SeventhCustomException;
}

然而,使用字典查找而不是几个OR语句和is检查会更好地提高性能吗?

这样的事情:

private bool ExceptionShouldNotify(Exception e)
{
    var dict = new Dictionary<String, int> {
        { "FirstCustomException",   1 },
        { "SecondCustomException",  1 },
        { "ThirdCustomException",   1 },
        { "FourthCustomException",  1 },
        { "FifthCustomException",   1 },
        { "SixthCustomException",   1 },
        { "SeventhCustomException", 1 }
    };

    return dict.ContainsKey(e.GetType().Name);
}

3 个答案:

答案 0 :(得分:5)

硬编码(第一个解决方案)是一个不好的做法,这就是为什么我投票支持字典(第二个解决方案),但我建议不同的实现:

   // HashSet - you don't use Value in the Dictionary, but Key
   // Type - we compare types, not their names
   private static HashSet<Type> s_ExceptionsToNotify = new HashSet<Type>() {
     typeof(FirstCustomException),
     typeof(SecondCustomException),
     ...
   };   

   // static: you don't use "this" in the method
   private static bool ExceptionShouldNotify(Exception e) {
     return s_ExceptionsToNotify.Contains(e.GetType());
   }

捕获到异常(包括堆栈跟踪),您已经有了很大的开销;这就是为什么性能(7个简单的比较与计算哈希)不是上下文中的主要问题

答案 1 :(得分:1)

如果要检查相当多的异常类型,查找字典是有意义的。但是,我会避免在此上下文中使用strings。您可以依赖Type类型:

var dict = new Dictionary<Type, int>()
{
    [typeof(FirstCustomerException)] = 1,
    [typeof(SecondCustomException)] = 1,
    ...
};

然后,您可以按例外对象的类型查找字典:

try
{
    ...
}
catch (Exception ex)
{
    int mapTo;
    if (dict.TryGetValue(ex.GetType(), out mapTo))
    {
        // Use mapTo value here
    }
}

您甚至可以使用C#6中称为异常过滤器的最新功能来捕获字典中存在的异常:

try
{
    ...
}
catch (Exception ex) when (dict.ContainsKey(ex.GetType())
{
    int mapTo = dict[ex.GetType()];
    // Use mapTo value here
}

这个实现稍慢一点,因为你必须两次调用GetType,并且还要执行两次字典映射。但它带来的好处是它保证你的catch块确实会处理异常,因为它只会输入映射中的异常而不是任何其他类型的异常。

答案 2 :(得分:0)

是的,应该。根据{{​​1}}文档,Dictionary方法接近O(1),而Contains语句链为O(N)。

https://msdn.microsoft.com/en-us/library/kw5aaea4(v=vs.110).aspx#Remarks

如果您使用or,我会更改密钥以使用the Dictionary来更有效地防止打字错误。