Oha*_*der 7 .net c# exception-handling
传统观点认为我们应该只捕获我们期望的特定异常类型:
try
{
int.Parse(str); //I am aware of TryParse(), this is just for the sake of example
}
catch (FormatException ex)
{
Console.WriteLine (ex);
}
catch (OverflowException ex)
{
Console.WriteLine (ex);
}
Run Code Online (Sandbox Code Playgroud)
但是,有时我们并不关心发生了哪个异常(只要它不是致命的),可能是因为我们只是想让用户知道发生了错误.在这些情况下,我们可以这样做:
try
{
Foo();
}
catch (Exception ex)
{
if (IsCriticalException(ex))
{
Environment.FailFast("System Error", ex);
}
Console.WriteLine ("Error running Foo: {0}", ex);
}
Run Code Online (Sandbox Code Playgroud)
在哪里IsCriticalException
可以类似地实施System.ClientUtils.IsCriticalException.由于以下几个原因,我一般都赞成这种方法:
ArgumentException
.有些方法甚至不能静态地知道它们可以抛出哪些异常,因为它们动态地加载其他模块/插件.据推测,他们可以用他们自己已知的例外情况包装所有这些"外部"例外,但我相信并非所有例外都有.这种方法的批评者认为方法的例外是其合同的一部分.如果抛出的异常不是本合同的一部分,我们应该假设其状态已损坏.我们还会在方法中发现一个错误(因为我们已经吞下了意外的异常,否则我们就不会发现这个错误).然后我们可以将这个bug传递给框架的开发人员,这是一个胜利 - 特别是如果这些开发人员在我们公司,所以我们"帮助自己"可以这么说.
我承认,批评者提出了有效的观点,但我觉得他们有点理想主义.实际上,我认为通用的非致命异常捕获在很多情况下都是有意义的.我有道理吗?
相关阅读:
传统观点认为我们应该只捕获我们期望的特定异常类型
实际上,我认为你应该准确地捕获那些你可以处理的异常。仅仅捕获异常并重新抛出它们是没有用的,并且让那些本来可以解决的异常通过也是没有意义的。
在上面的示例中,我认为有一个包罗万象的块就可以了,毕竟不转换该字符串是一个可恢复的错误,无论弹出什么异常(除了 OutOfMemoryException ,它无论如何都无法处理,因为任何尝试处理会使用内存)。