2016-12-14 57 views
1

我有一个方法来检查传入的异常并返回一个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); 
} 
+0

你的基准测试告诉你什么? –

+0

在字典的情况下,我宁愿将它实现为'HashSet ' –

+0

当你处于故障路径时,你真的关心性能吗?你是否期望你的客户说:“好吧,它倒下了,但它真的*快!” –

回答

5

硬编码(第1溶液)是一种不好的做法,这就是为什么我投词典(第2溶液),但我建议不同的实现的想法:

// 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简单比较与计算散列)不是上下文中的主要问题

+0

我试过类似这样的 类型y = ex。的GetType(); 开关(Y) { 情况下的typeof(FirstCustomException): 情况下的typeof(SecondCustomException): 情况下的typeof(ThirdCustomException): 情况下的typeof(FourthCustomException): 情况下的typeof(FifthCustomException): 情况下的typeof(SixthCustomException): case typeof(SeventhCustomException): return true; 休息; 默认值: 返回false; } 但它表示错误为“开关表达式或案例标签必须是布尔型,字符型,字符串型,积分型,枚举型或相应的可空类型”。你能解释一下为什么交换机不能和“Type”配合使用。 –

+0

@Sethu Bala:请不要*硬编码*:单独*数据*(即异常类型)和*源代码*(不应该依赖于数据) –

+0

我明白了这一点,但我的疑问就是为什么切换大小写不适用于Type。 –

1

如果您有相当数量的异常类型需要检查,查找字典是很有意义的。不过,我会避免在这方面使用strings。你可以依靠Type类型,而不是:

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

你甚至可以使用从C#6名为例外的最新功能:

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

然后,您可以通过异常对象的类型查字典过滤器,只赶上那些存在于词典中的例外:

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

这个实现是一个稍微有点慢,因为你必须调用GetType两次,并且还执行两次字典映射。但它带来的好处是它可以确保您的catch块确实能够处理异常,因为它仅用于映射中的异常,而不用于任何其他类型的异常。