我刚刚看到一个关于try-catch的问题,哪些人(包括Jon Skeet)认为空catch块是一个非常糟糕的主意?为什么呢?在任何情况下,空接点都不是错误的设计决策吗?

我的意思是,例如,有时你想从某个地方(webservice,数据库)获得一些额外的信息,你真的不关心你是否会得到这个信息。所以你试着获取它,如果发生了什么,没关系,我只会添加一个“catch (Exception ignored){}”,仅此而已


当前回答

在某些情况下,您可能会使用它们,但它们应该非常不频繁。我可能会使用它的情况包括:

异常日志记录;根据上下文的不同,您可能希望发布一个未处理的异常或消息。 循环技术情况,如渲染或声音处理或列表框回调,行为本身将演示问题,抛出异常将只是阻碍,记录异常可能只会导致1000个“失败到XXX”消息。 不能失败的程序,尽管它们至少应该记录一些东西。

对于大多数winforms应用程序,我发现对于每个用户输入都有一个try语句就足够了。我使用以下方法:(AlertBox只是一个快速的消息框。显示包装)

  public static bool TryAction(Action pAction)
  {
     try { pAction(); return true; }
     catch (Exception exception)
     {
        LogException(exception);
        return false;
     }
  }

  public static bool TryActionQuietly(Action pAction)
  {
     try { pAction(); return true; }
     catch(Exception exception)
     {
        LogExceptionQuietly(exception);
        return false;
     }
  }

  public static void LogException(Exception pException)
  {
     try
     {
        AlertBox(pException, true);
        LogExceptionQuietly(pException);
     }
     catch { }
  }

  public static void LogExceptionQuietly(Exception pException)
  {
     try { Debug.WriteLine("Exception: {0}", pException.Message); } catch { }
  }

然后每个事件处理程序都可以这样做:

  private void mCloseToolStripMenuItem_Click(object pSender, EventArgs pEventArgs)
  {
     EditorDefines.TryAction(Dispose);
  }

or

  private void MainForm_Paint(object pSender, PaintEventArgs pEventArgs)
  {
     EditorDefines.TryActionQuietly(() => Render(pEventArgs));
  }

理论上,您可以使用tryactionsilent,它可能更适合呈现调用,这样异常就不会生成无穷无尽的消息。

其他回答

因为如果抛出异常,您将永远不会看到它——默默地失败是最糟糕的选择——您将得到错误的行为,而且不知道它发生在哪里。至少在那里放一条日志消息!即使是“不可能发生”的事情!

只有在确实出现异常时才应该抛出异常——发生了超出正常范围的事情。一个空的catch块基本上表示“一些不好的事情正在发生,但我只是不在乎”。这是个坏主意。

如果您不想处理异常,就让它向上传播,直到它到达一些可以处理它的代码。如果没有任何东西可以处理异常,则应该关闭应用程序。

一个空的catch块本质上是在说“我不想知道抛出了什么错误,我只是忽略它们。”

它类似于VB6的On Error Resume Next,除了异常抛出后try块中的任何内容将被跳过。

如果有东西坏了,这也没用。

我不会把事情延伸到说使用空catch块的人是一个糟糕的程序员,不知道他在做什么……

如果需要,我使用空捕捉块。有时我正在使用的库的程序员不知道他在做什么,甚至在没有人需要的情况下抛出异常。

例如,考虑一些http服务器库,如果服务器抛出异常,因为客户端已断开连接,index.html无法发送,我不会太在意。

这可能从来都不是正确的事情,因为您正在默默地传递每个可能的异常。如果有您期望的特定异常,那么您应该测试它,如果它不是您的异常则重新抛出。

try
{
    // Do some processing.
}
catch (FileNotFound fnf)
{
    HandleFileNotFound(fnf);
}
catch (Exception e)
{
    if (!IsGenericButExpected(e))
        throw;
}

public bool IsGenericButExpected(Exception exception)
{
    var expected = false;
    if (exception.Message == "some expected message")
    {
        // Handle gracefully ... ie. log or something.
        expected = true;
    }

    return expected;
}