6

如果我有这样的事情怎么办:

try
{
   //work
}
catch (ArgumentNullException e)
{
   HandleNullException();
   Logger.log("ArgumentNullException " + e);
   DoSomething();
}
catch (SomeOtherException e)
{
   HandleSomeOtherException();
   Logger.log("SomeOtherException " + e);
   DoSomething();
}
catch (Exception e)
{
   HandleException();
   Logger.log("Exception " + e);
   DoSomething();
}

现在我们可以看到,我正在尝试处理一些不同情况的异常。但是每当引发异常时,我总是DoSomething()在最后调用该方法。DoSomething()如果出现异常,是否有更智能的调用方式?如果我添加一个finally块并DoSomething()在那里调用,它总是会被调用,即使没有例外。有什么建议么?

4

6 回答 6

9

如果我添加一个finally块并DoSomething()在那里调用,它总是会被调用,即使没有例外。

您要查找的内容在CLI 标准(分区 IIA,第 18 章)中称为故障处理程序。尽管 .NET 实现了它们,但 C# 语言并不直接支持它们。但是,可以模拟它们:

bool success = false;
try
{
    …
    success = true;
}
catch (…)
{
    …
}
…
finally
{
    if (!success)
    {
        DoSomething();
    }
}

catch请注意,正如这里的一些答案所建议的那样,不需要在每个处理程序中设置标志。简单地否定测试,你只需要在块的末尾设置一次标志try

于 2013-01-12T21:43:05.197 回答
5

您可以使用以下代码,它实际上确实删除了冗余。

try
{
    //work
}
catch (Exception e)
{
    Handle(e);
}

方法在哪里Handle

static void Handle(Exception e)
{
    var exceptionType = e.GetType();
    //Use an if/else block, or use a Dictionary<Type, Action>
    //to operate on your exception
    Logger.log(exceptionType + " " + e);
    DoSomething();
}
于 2013-01-12T21:47:51.393 回答
2

你现在正在做的事情已经做得很好了。

如果您需要在发生异常时调用此函数,而不是其他情况,并且您必须使用不同的代码来处理不同的异常,那么这是可以做到的最好的方法。

于 2013-01-12T21:41:42.043 回答
2

您可以在抛出异常时设置布尔值,使用finally并检查布尔值。(或者相反,只在没有抛出异常时才设置布尔值,如下图:)

bool noException = false;
try
{
    //work
    noException = true;
}
catch (ArgumentNullException e)
{
    HandleNullException();
    Logger.log("ArgumentNullException " + e);
}
catch (SomeOtherException e)
{
    HandleSomeOtherException();
    Logger.log("SomeOtherException " + e);
}
catch (Exception e)
{
    HandleException();
    Logger.log("Exception " + e);
}
finally
{
    if (!noException)
        DoSomething();
}
于 2013-01-12T21:42:47.383 回答
2

为什么不只是:

try
{
    //work
}
catch (Exception e)
{
    if (e is ArgumentNullException)
      HandleNullException();
    else if (e is SomeOtherException)
      HandleSomeOtherException();
    else
      HandleException();
    Logger.log(e.GetType().Name + " " + e);
    DoSomething();
}

记录的类型名称将是实际的运行时类型,因此例如"IndexOutOfRangeException"可能会记录而不是仅"Exception"当您处于情况三时,但我认为这是对您现在所拥有的内容的改进。

编辑:上面的代码看起来很糟糕if-<code>else if 逻辑检查类型。如果我们引入多态,它可能会更漂亮:

try
{
    //work
}
catch (HandleableException e)
{
    e.Handle();  // this calls a **virtual** method, each override does what's relevant
    Logger.log(e.GetType().Name + " " + e);
    DoSomething();
}

当然,如果Exception我们不能修改一些有问题的类,就不可能给它们一个Handle()方法。.Handle()也可以是扩展方法(而不是实例virtual方法),但是类型检查(丑陋的代码)必须在该方法内完成。然后这变得与夏娃的答案非常相似。

于 2013-01-12T22:32:51.653 回答
1

你可以这样做:

Exception caughtException = null;
try {
    ...
} catch(ExceptionType1 e1) {
    ...
    caughtException = e1;
} catch(ExceptionType2 e2) {
    ...
    caughtException = e2;
} catch(ExceptionType3 e3) {
    ...
    caughtException = e3;
}
if (caughtException != null) {
    // Put your common exception code here
    DoSomenthing();
    // You can pass caughtException to functions, too
    LogException(caughtException);
}

caughtExceptionnull除非捕获到异常,否则将是。您可以使用它来决定是否打电话DoSomenthing

于 2013-01-12T21:43:02.243 回答