一次捕获多个异常?

仅仅捕获System.Exception就不鼓励了。 相反,只有“已知”的例外应该被捕获。

现在,这有时会导致不必要的重复代码,例如:

try
{
    WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
    WebId = Guid.Empty;
}
catch (OverflowException)
{
    WebId = Guid.Empty;
}

我想知道:有没有办法来捕获这两个异常,只调用一次WebId = Guid.Empty调用?

给出的例子很简单,因为它只是一个GUID 。 但想象一下代码,您可以多次修改对象,并且如果某个操作以预期的方式失败,那么您希望“重置”该object 。 但是,如果出现意想不到的例外,我仍然想要更高一些。


捕获System.Exception并打开类型

catch (Exception ex)            
{                
    if (ex is FormatException || ex is OverflowException)
    {
        WebId = Guid.Empty;
        return;
    }

    throw;
}

编辑:我同意其他人说,从C#6.0开始,异常过滤器现在是一个非常好的方法: catch (Exception ex) when (ex is ... || ex is ... )

除此之外,我仍然讨厌一条龙线的布局,并且会亲自将代码放在下面。 我认为这是一样的功能,因为它是审美,因为我相信它提高了理解。 有些人可能不同意:

catch (Exception ex) when (
    ex is ...
    || ex is ...
    || ex is ...
)

原版的:

我知道我在这里参加派对有点晚,但是神圣的烟雾......

直截了当地追逐,这种复制了一个早期的答案,但是如果你真的想为几个异常类型执行一个共同的操作,并且保持整个事物在一个方法的范围内整齐和整齐,为什么不使用lambda /闭合/内联函数来做类似下面的事情? 我的意思是,你很可能会意识到你只是想让这个闭包成为一个单独的方法,你可以在整个地方使用。 但是,如果不从结构上实际改变代码的其余部分,这将非常容易。 对?

private void TestMethod ()
{
    Action<Exception> errorHandler = ( ex ) => {
        // write to a log, whatever...
    };

    try
    {
        // try some stuff
    }
    catch ( FormatException  ex ) { errorHandler ( ex ); }
    catch ( OverflowException ex ) { errorHandler ( ex ); }
    catch ( ArgumentNullException ex ) { errorHandler ( ex ); }
}

我忍不住想知道( 警告:前面有点讽刺/讽刺)为什么地球上所有这些努力基本上只取代了以下几点:

try
{
    // try some stuff
}
catch( FormatException ex ){}
catch( OverflowException ex ){}
catch( ArgumentNullException ex ){}

...下面的代码味道有些疯狂的变化,我的意思是例子,只是假装你保存了几个按键。

// sorta sucks, let's be honest...
try
{
    // try some stuff
}
catch( Exception ex )
{
    if (ex is FormatException ||
        ex is OverflowException ||
        ex is ArgumentNullException)
    {
        // write to a log, whatever...
        return;
    }
    throw;
}

因为它当然不会自动更具可读性。

当然,我留下了/* write to a log, whatever... */ return;的三个相同的实例/* write to a log, whatever... */ return; 出于第一个例子。

但这是我的观点。 你们都听说过功能/方法,对吧? 认真。 编写一个通用的ErrorHandler函数,就像从每个catch块中调用它。

如果你问我,第二个例子(使用ifis关键字)的可读性明显降低,同时在项目的维护阶段同时出现更多的错误。

任何对编程相对陌生的人来说,维护阶段将占项目整个生命周期的98.7%或更多,而进行维护的可怜的schmuck几乎肯定会成为除你之外的其他人。 而且他们很可能会花50%的时间在工作上诅咒自己的名字。

当然FxCop的呵斥你,所以你必须添加到您的代码属性已精确拉链与正在运行的程序做的,只是没有告诉的FxCop忽视的一个问题是,在案件99.9%,这是完全正确标记。 而且,对不起,我可能会误解,但是不会将“忽略”属性最终编译到您的应用程序中?

将整个if测试放在一条线上使其更具可读性? 我不这么认为。 我的意思是,我确实有另一位程序员在很久以前激烈地争论说,将更多代码放在一行上会使其“跑得更快”。 但他当然是疯狂的疯狂。 试图向他解释(这是一个直面 - 这是一个挑战)解释者或编译器如何将这条长长的行分成单行的单行指令语句 - 如果他继续前进,并且与结果基本相同只是让代码可读,而不是试图超越编译器 - 对他没有任何影响。 但我离题了。

当你从现在开始增加三个或更多的异常类型时,它会得到多少可读性? (答案:它可读性差很多 )。

其中一个主要问题的确是,格式化我们每天都在看的文本源代码的大部分要点是,让代码运行时真正发生的实际情况对其他人是非常明显的。 因为编译器会将源代码转换成完全不同的东西,并且不会在乎您的代码格式化风格。 所以一对一的线也完全烂了。

只是说...

// super sucks...
catch( Exception ex )
{
    if ( ex is FormatException || ex is OverflowException || ex is ArgumentNullException )
    {
        // write to a log, whatever...
        return;
    }
    throw;
}

正如其他人所指出的,你可以在你的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编译器进行构建,而不是任何系统安装的版本。

链接地址: http://www.djcxy.com/p/4389.html

上一篇: Catch multiple exceptions at once?

下一篇: Blocks and yields in Ruby