很多catch块,但在所有catch块中都有相同的功能

时间:2013-01-12 21:39:34

标签: c# .net exception try-catch

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

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(),那么即使没有异常,也会一直调用它。有什么建议吗?

6 个答案:

答案 0 :(得分:9)

  

如果我添加了finally块并在那里调用了DoSomething(),那么即使没有例外,也会一直调用它。

您所寻找的内容在CLI standard(分区IIA,第18章)中称为fault handler。尽管.NET实现了它们,但C#语言并不直接支持它们。但是,他们可以被模仿:

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

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

答案 1 :(得分: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();
}

答案 2 :(得分:2)

你现在正在做的事情和它一样好。

如果你需要在发生异常时调用此函数,而不是其他情况,并且你必须有不同的代码来处理不同的异常,这是最好的。

答案 3 :(得分: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();
}

答案 4 :(得分: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 - 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实例方法),但是必须在该方法内完成类型检查(丑陋代码)。然后这与Eve的回答非常相似。

答案 5 :(得分: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);
}
除非发现异常,否则

caughtException将为null。您可以使用它来决定是否致电DoSomenthing