不鼓励只捕获System.Exception。相反,只应捕获“已知”异常。
现在,这有时会导致不必要的重复代码,例如:
try
{
WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
WebId = Guid.Empty;
}
catch (OverflowException)
{
WebId = Guid.Empty;
}
我想知道:是否有一种方法可以捕获两个异常,并且只调用WebId=Guid.Empty调用一次?
给定的示例相当简单,因为它只是一个GUID。但是想象一下,在代码中,您多次修改一个对象,如果其中一个操作预期失败,您希望“重置”该对象。然而,如果有意外的异常,我仍然想把它推得更高。
约瑟夫·戴格尔的答案是一个很好的解决方案,但我发现下面的结构更整洁,更不容易出错。
catch(Exception ex)
{
if (!(ex is SomeException || ex is OtherException)) throw;
// Handle exception
}
反转表达式有几个优点:
return语句不是必需的代码未嵌套不存在忘记“抛出”或“返回”语句的风险,这些语句在Joseph的解决方案中与表达式分离。
它甚至可以压缩成一行(虽然不是很漂亮)
catch(Exception ex) { if (!(ex is SomeException || ex is OtherException)) throw;
// Handle exception
}
编辑:C#6.0中的异常过滤将使语法更加简洁,并比任何当前解决方案都有许多其他好处。(最值得注意的是,未损坏堆栈)
下面是使用C#6.0语法时相同问题的外观:
catch(Exception ex) when (ex is SomeException || ex is OtherException)
{
// Handle exception
}
约瑟夫·戴格尔的答案是一个很好的解决方案,但我发现下面的结构更整洁,更不容易出错。
catch(Exception ex)
{
if (!(ex is SomeException || ex is OtherException)) throw;
// Handle exception
}
反转表达式有几个优点:
return语句不是必需的代码未嵌套不存在忘记“抛出”或“返回”语句的风险,这些语句在Joseph的解决方案中与表达式分离。
它甚至可以压缩成一行(虽然不是很漂亮)
catch(Exception ex) { if (!(ex is SomeException || ex is OtherException)) throw;
// Handle exception
}
编辑:C#6.0中的异常过滤将使语法更加简洁,并比任何当前解决方案都有许多其他好处。(最值得注意的是,未损坏堆栈)
下面是使用C#6.0语法时相同问题的外观:
catch(Exception ex) when (ex is SomeException || ex is OtherException)
{
// Handle exception
}
正如其他人所指出的,您可以在catch块中使用if语句来确定发生了什么。C#6支持异常过滤器,因此以下操作将起作用:
try { … }
catch (Exception e) when (MyFilter(e))
{
…
}
MyFilter方法可能看起来像这样:
private bool MyFilter(Exception e)
{
return e is ArgumentNullException || e is FormatException;
}
或者,这可以全部内联完成(when语句的右侧必须是布尔表达式)。
try { … }
catch (Exception e) when (e is ArgumentNullException || e is FormatException)
{
…
}
这与在catch块中使用if语句不同,使用异常过滤器不会展开堆栈。
您可以下载Visual Studio 2015来查看。
如果要继续使用Visual Studio 2013,可以安装以下nuget包:
安装程序包Microsoft.Net.Compilers
在撰写本文时,这将包括对C#6的支持。
引用此包将导致使用中包含的C#和Visual Basic编译器的特定版本与任何系统安装版本不同。