我刚刚看到一个 关于try-catch的问题, ,哪些人(包括乔恩·斯基特)说空的 catch 块是一个非常糟糕的主意?为什么这个?是否存在空捕获不是错误设计决策的情况?

我的意思是,例如,有时您想从某个地方(网络服务、数据库)获取一些附加信息,而您实际上并不关心是否会获取这些信息。所以你尝试获取它,如果发生任何事情,那没关系,我只添加一个“catch(忽略异常){}”,仅此而已

有帮助吗?

解决方案

通常是空的try-catch是一个糟糕的主意,因为你是默默吞咽错误状态,然后继续执行。有时这可能是做正确的事,但很多情况下,开发者看到了异常的迹象,不知道该怎么办才好,所以使用空抓沉默问题。

这是编程等效将黑色胶带上的发动机警示灯的

我相信,你如何处理异常取决于你工作的软件是什么层:的在雨林例外。

其他提示

他们是一个坏主意的一般的,因为它是一个地方失败(异常情况,更一般地)正确会见了没有任何响应一个真正难得的条件。最重要的是,空catch块是通过谁使用异常引擎错误检查,他们应该抢先做的人使用的常用工具。

要说它的总是的不好是不真实的...这是非常小的事实。可以有下述情形之一,你不在乎,有一个错误或错误的存在在某种程度上表明,你不能做任何事情反正(例如情况下,写了以前的错误,以一个文本日志文件时和你会得到一个IOException,这意味着你不能这么写出来的新的错误)。

我不舒展的东西尽可能地说,谁使用空的catch块是一个糟糕的程序员,不知道他在做什么......

我用空catch块如果必要的话。有时候库我耗时不知道他正在做什么和程序员,当没有人需要它抛出,即使在情况异常。

例如,考虑一些HTTP服务器库,如果服务器,因为客户端已断开,index.html无法发送抛出异常,我一点也不在乎。

有其中可以合理罕见的情况。在Python你经常会看到这样的结构:

try:
    result = foo()
except ValueError:
    result = None

因此,它可能是OK(取决于您的应用程序)来执行:

result = bar()
if result == None:
    try:
        result = foo()
    except ValueError:
        pass # Python pass is equivalent to { } in curly-brace languages
 # Now result == None if bar() returned None *and* foo() failed

在最近的.NET项目,我不得不写代码来枚举插件DLL文件找到实现某个接口的类。的代码中的相关位(在VB.NET,对不起)是:

    For Each dllFile As String In dllFiles
        Try
            ' Try to load the DLL as a .NET Assembly
            Dim dll As Assembly = Assembly.LoadFile(dllFile)
            ' Loop through the classes in the DLL
            For Each cls As Type In dll.GetExportedTypes()
                ' Does this class implement the interface?
                If interfaceType.IsAssignableFrom(cls) Then

                    ' ... more code here ...

                End If
            Next
        Catch ex As Exception
            ' Unable to load the Assembly or enumerate types -- just ignore
        End Try
    Next

虽然即使在这种情况下,我会承认,地方登录失败可能会是一个进步。

空的catch块通常放在因为编码器并不知道自己在做什么。在我的组织,一个空的catch块必须包括为何无所事事,不同之处是一个好主意评论。

在一个相关的说明,大多数人不知道,一试{}块可跟任何一个catch {}或finally {},只需要一个。

如果是真正的例外

例外只能被抛出 - 出事超越常态。一个空的catch块基本上说“坏事发生的事情,但我不在乎。”这是一个好主意。

如果你不想处理异常,让它向上传播,直到它到达一些代码,可以处理它。如果没有能处理异常,应采取的申请下来。

我认为这没关系,如果你赶上的尤其的例外,这你知道它一定会得到提升的一个的特别的原因,你想到的是例外,真正类型不需要做任何事情。

但是,即使在这种情况下,调试消息可能是为了

乔什·布洛赫 - 第 65 项:不要忽视异常有效的Java:

  1. 空的 catch 块违背了异常的目的
  2. 至少,catch 块应该包含一个注释,解释为什么忽略异常是合适的。

这是空的catch块基本上是说:“我不想知道是什么抛出的错误,我只是去忽略他们。”

这是类似于VB6的On Error Resume Next,除了在try块抛出异常将被跳过之后的事情。

这不利于事情的时候休息,然后

此去手在手,“不要使用异常来控制程序的流程。”,并且,“只使用例外情况除外。”如果这些都做了,那么例外只应在有问题发生。如果有问题,你不想静默失败。在罕见的异常,其中,没有必要来处理这个问题,你至少应该记录异常,以防万一异常变得不再异常。唯一比没有被悄悄失败还要糟糕。

我觉得完全是空的catch块是一个糟糕的主意,因为没有办法推断忽略了的例外是代码的预期行为。这不一定是坏事吞下一个例外,在某些情况下返回false或空或其他一些价值。 .NET Framework中有这样的行为,许多“尝试”的方法。根据经验,如果你吞下一个例外的规则,如果该应用程序支持日志添加注释和日志语句。

因为如果一个异常的的抛出你永远不会看到它 - 默默失败是最糟糕的选择 - 你会得到错误的行为,不知道该看哪里,它的发生。至少放一个记录信息有!即使它的东西,“可能永远不会发生”!

空catch块是一个程序员的指示不知道如何处理的异常做。它们是由可能向上冒泡,并正由另一try块正确处理抑制异常。总是尝试做与你捕捉异常的东西。

我找到空catch语句最可气的是,当其他一些程序员做到了。我的意思是,当你从别人需要调试代码否则任何空catch语句使得这样的承诺更难以则需要的人。恕我直言catch语句应始终显示某种错误消息的 - (ALT仅在调试模式下),即使不处理的错误它至少应该检测到它

这可能永远是正确的,因为你是默默传递的每一个的可能是个例外。如果有你期待一个特定的异常,那么你应该测试它,重新抛出,如果它不是你的例外。

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;
}

一般情况下,你应该只抓住你其实可以处理的异常。这意味着捕获异常时要尽可能具体。捕获所有异常是很少一个好主意,忽略所有异常几乎总是一个非常糟糕的主意。

我只能认为其中一个空的catch块具有一些有意义的目的几个实例。如果任何特定的异常,你正赶上被“处理”的只是重新尝试的动作就没有必要做在catch块东西。但是,它仍然会记录异常发生的事实是一个好主意。

又如:CLR 2.0改变终结器线程上未处理的异常进行处理的方式。在此之前2.0的过程中被允许生存的这个场景。在当前的CLR过程终止在终结器线程上的未处理的异常的情况下

请记住,你应该只执行终结如果你真的需要一个,甚至,那么你应该在终结做越少越好。但是,如果不管你的工作必须终结做可以抛出一个异常,则需要两两害相权之间的较小挑。你想关闭应用程序由于未处理的异常?或者你想在或多或少的不确定的状态继续吗?至少在理论上,后者可以是两害中的较小者在某些情况下。在这些情况下,空的catch块将阻止终止该进程。

我的意思是,比如,有时你想从某个地方(web服务,数据库),一些额外的信息,你真的不在乎,如果你会得到这样的信息或没有。所以,你设法得到它,如果有什么事情发生,那没关系,我只添加一个“赶上(例外忽略){}”,这一切

所以,你的榜样去,它在这种情况下,一个糟糕的主意,因为你捕捉和忽略的所有的异常。如果你只抓住和EInfoFromIrrelevantSourceNotAvailable忽视它,那将是很好,但你不是。你还忽略ENetworkIsDown,这可能是也可能不是很重要。你忽略ENetworkCardHasMeltedEFPUHasDecidedThatOnePlusOneIsSeventeen,这几乎肯定是很重要的。

这是空的catch块是不是如果它设置为唯一的缺点(和忽略)某些类型的,你知道是不重要的异常的问题。其中,这是一个好主意的情况下,以抑制和默默地忽略的所有的例外,没有停下来先检查,看看它们是否正在期待/正常/无关与否,是极其罕见的。

在某些情况下您可能会使用它们,但这种情况应该很少见。我可能使用的情况包括:

  • 异常记录;根据上下文,您可能需要未处理的异常或发布消息。

  • 循环技术情况,例如渲染或声音处理或列表框回调,其中行为本身将演示问题,抛出异常只会造成妨碍,并且记录异常可能只会导致 1000 条“xxx 失败”消息。

  • 程序 不能 失败,尽管他们至少应该记录一些东西。

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

  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);
  }

或者

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

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

您永远不应该有一个空的catch块。它就像躲在你知道错了。至少,如果你时间紧迫,你应该写一个异常到日志文件以供以后查阅。

如果你不知道该怎么在catch块做,你可以只需登录此异常,但不留空白。

        try
        {
            string a = "125";
            int b = int.Parse(a);
        }
        catch (Exception ex)
        {
            Log.LogError(ex);
        }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top