代码之家  ›  专栏  ›  技术社区  ›  Samuel Carrijo

为什么空的捕获块是个坏主意?[闭门]

  •  168
  • Samuel Carrijo  · 技术社区  · 15 年前

    我刚看过一本书 question on try-catch

    我的意思是,举例来说,有时候你想从某处获得一些额外的信息(Web服务、数据库),而你真的不在乎你是否能获得这些信息。所以你试着得到它,如果发生了什么,没关系,我只添加一个“catch(Exception-ignored){}”,就这样

    20 回复  |  直到 7 年前
        1
  •  308
  •   Ned Batchelder    15 年前

    通常,空的try-catch是个坏主意,因为您正在默默地接受错误条件,然后继续执行。偶尔这可能是正确的做法,但通常这是一个迹象,表明开发人员看到了异常,不知道如何处理它,因此使用了一个空捕获来消除问题。

    这相当于在发动机警示灯上贴上黑色胶带。

    Exceptions in the Rainforest .

        2
  •  38
  •   Adam Robinson    15 年前

    这是个坏主意 因为这是一种真正罕见的情况,在这种情况下,故障(更一般地说,是异常情况)被正确地满足,而没有任何响应。最重要的是,空的 catch 块是使用异常引擎进行错误检查的人常用的工具,他们应该先发制人地进行错误检查。

    总是 坏的是不真实的…很少是真的。在某些情况下,您可能不关心是否存在错误,或者错误的存在以某种方式表明您无论如何都无法对其进行任何处理(例如,在将以前的错误写入文本日志文件时,您会得到一个 IOException ,这意味着您无论如何都无法写出新错误)。

        3
  •  11
  •   lubos hasko    15 年前

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

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

    例如,考虑一些HTTP服务器库,我不关心服务器是否因为客户端已断开而抛出异常。 index.html

        4
  •  9
  •   Reed Copsey    15 年前

        5
  •  9
  •   balpha    15 年前

    我想如果你抓到一个 异常类型,您知道它只针对一个 特指的 原因,你期待着这个例外,真的不需要做任何事情。

        6
  •  8
  •   Daniel Pryden    15 年前

    很少有情况可以证明这一点。在Python中,您经常看到这种构造:

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

    因此,可以(取决于您的应用程序)执行以下操作:

    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
    

    尽管即使在这种情况下,我也承认在某个地方记录失败可能是一种改进。

        7
  •  7
  •   Justin    15 年前

    空的catch块通常被放入,因为编码器并不真正知道它们在做什么。在我的组织中,一个空的catch块必须包含一条注释,说明为什么在异常情况下什么都不做是个好主意。

    另一方面,大多数人不知道try{}块后面可以跟catch{}或finally{},只需要一个。

        8
  •  7
  •   KrishPrabakar    10 年前

    乔什·布洛赫 - 第65项:不要忽略例外情况 属于 Effective Java :

    1. 至少,catch块应该包含一条注释,解释为什么忽略异常是合适的。
        9
  •  3
  •   Powerlord    15 年前

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

    它类似于VB6 On Error Resume Next ,但将跳过引发异常后try块中的任何内容。

    如果有东西坏了,那就没用了。

        10
  •  3
  •   Imagist    15 年前

    这与“不要使用异常来控制程序流”和“仅在异常情况下使用异常”密切相关。如果这些都完成了,那么异常应该只在出现问题时发生。如果有问题,你不想默默地失败。在不需要处理问题的罕见异常中,您至少应该记录异常,以防异常不再是异常。唯一比失败更糟糕的是默默地失败。

        11
  •  2
  •   Dan    15 年前

    空的catch块表示程序员不知道如何处理异常。它们正在抑制异常可能冒泡并被另一个try块正确处理。总是试着做一些你发现的例外情况。

        12
  •  2
  •   complexcipher    15 年前

    我认为完全空的catch块是个坏主意,因为无法推断忽略异常是代码的预期行为。在某些情况下,吞并异常并返回false、null或其他值并不一定是坏事。net framework有许多“try”方法都是这样的。根据经验,如果您接受异常,如果应用程序支持日志记录,请添加注释和日志语句。

        13
  •  1
  •   Nate    15 年前

    因为如果有例外 你永远也看不到它——默默地失败是最糟糕的选择——你会有错误的行为,不知道发生了什么。至少在那里放一条日志信息!即使这是“永远不会发生”的事情!

        14
  •  1
  •   AndersK    15 年前

    我发现空的catch语句最让人恼火的是当其他程序员这样做的时候。我的意思是,当您需要调试来自其他人的代码时,任何空的catch语句都会使这样的任务变得更加困难。IMHO catch语句应始终显示某种类型的错误消息-即使未处理错误,也应至少检测到它(仅在调试模式下alt.on)

        15
  •  1
  •   xanadont    15 年前

    这可能永远都不是正确的事情,因为你在默默地走过

    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;
    }
    
        16
  •  1
  •   Brian Rasmussen    15 年前

    我只能想到几个例子,其中一个空的catch块有一些有意义的用途。如果捕获的任何特定异常都是通过重新尝试操作来“处理”的,则无需在catch块中执行任何操作。但是,记录异常发生的事实仍然是一个好主意。

    另一个示例:CLR 2.0更改了终结器线程上未处理异常的处理方式。在2.0之前,该流程允许在这种情况下生存。在当前CLR中,如果终结器线程上出现未处理的异常,进程将终止。

    请记住,只有在确实需要终结器时才应该实现终结器,即使这样,您也应该在终结器中尽可能地执行一点操作。但是,如果终结器必须做的任何工作都可能引发异常,那么您需要在两个缺点中选择较小的一个。由于未处理的异常,是否要关闭应用程序?或者您想在或多或少未定义的状态下继续吗?至少在理论上,在某些情况下,后者可能是两种邪恶中较小的一种。在这种情况下,空的catch块将阻止进程终止。

        17
  •  1
  •   Dave Sherohman    15 年前
    我的意思是,举例来说,有时候你想从某处获得一些额外的信息(Web服务、数据库),而你真的不在乎你是否能获得这些信息。所以你试着得到它,如果发生了什么,没关系,我只添加一个“catch(Exception-ignored){}”,就这样

    所以,以你的例子来说,在这种情况下,这是一个坏主意,因为你抓住了,忽略了 全部的 EInfoFromIrrelevantSourceNotAvailable ENetworkIsDown ,这可能重要,也可能不重要。你忽视了 ENetworkCardHasMelted EFPUHasDecidedThatOnePlusOneIsSeventeen ,这几乎可以肯定是重要的。

    如果将空catch块设置为只捕获(并忽略)您知道不重要的某些类型的异常,则空catch块不是问题。在这种情况下,最好是压制,然后默默地忽略 全部的

        18
  •  1
  •   Dave Cousineau    13 年前

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

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

    • 循环技术情况,如渲染、声音处理或列表框回调,其中行为本身会证明问题,抛出异常只会造成阻碍,记录异常可能只会导致1000条“failed to 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));
      }
    

        19
  •  1
  •   Andzej Maciusovic    11 年前

            try
            {
                string a = "125";
                int b = int.Parse(a);
            }
            catch (Exception ex)
            {
                Log.LogError(ex);
            }
    
        20
  •  0
  •   Chadit    15 年前