问题 何时使用以及何时不使用Try Catch Finally


我在.net 3.5中创建asp.net web应用程序,我想知道何时使用以及何时不使用Try Catch Finally块?特别是,我的大部分try catch都围绕执行存储过程并填充文本字段或网格视图?你会用Try Catch吗? 每次 当您执行存储过程并填充数据显示控件?

我的代码块通常如下所示:

    protected void AddNewRecord()
    {
        try
        {
           //execute stored proc
           // populate grid view controls or textboxes
        }
        catch (Exception ex)
        {
           //display a messagebox to user that an error has occured
           //return
        }
        finally
        { }
   }

8877
2017-07-06 12:57


起源

也看到了这个: stackoverflow.com/questions/505471/... - 0x49D1
查看由J. Richter撰写的第3版“CLR via C#”一书。它非常详细地介绍了异常处理概念,绝对是一个很好的参考。 - ileon


答案:


答案是“它取决于”。

您可能想要使用 try{...} catch {...} 围绕每个原子操作,以便在出现问题时可以回滚到上一个良好状态(使用事务)。这可能是一个或多个存储过程 - 这取决于您的应用程序。

如果要捕获异常,请确保明确指出捕获的异常。你不应该 catch (Exception ex) 要么 catch()  - 称为“catch all”异常处理 - 但具有特定的catch语句 catch (IndexOutOfRangeException ex) (例如)改为。

但是,如果您无法处理异常或者您无法清除任何内容,那么您不应该捕获它。


10
2017-07-06 13:00



“原子”操作是什么意思? - user279521
en.wikipedia.org/wiki/Atomic_operation - Dan McClain
@ user279521 - “原子” - 就像一个原子一样,它无法进一步划分。它可能有许多步骤,但如果按照自己的步骤执行,则每个步骤都没有意义。例如,如果您修复了代码中的错误但需要编辑许多类,则所有文件的签入都被认为是原子的,因为只检入一个没有任何意义。 - ChrisF♦
@phsr - 感谢您的链接! - ChrisF♦
@Chris S - 如果你会变得迂腐;)它来自希腊语,ἄτομος(átomos),意思是不可切割/不可分割。 - ChrisF♦


你应该只使用 try catch,当你打算在catch块中处理异常时。我的意思是句柄,记录错误,选择不同的路径,因为错误等。如果你只是打算重新投掷它,没有必要尝试捕获。


4
2017-07-06 13:06



如果要记录错误,则无需在发生异常时捕获异常 - 而是可以在代码的出口处捕获异常,从而记录代码中任何位置发生的异常。 - Polyfun
你提出了一个很好的观点,但我认为这在很大程度上取决于应用程序的整体架构。我真的只是提供它作为何时可能使用try catch的一个例子。 - kemiller2002
如果对象的不变量依赖于块中的所有代码执行会怎么样?我认为在这种情况下,代码应该由一个块来保护,如果在对象的不变量可能不成立时发生异常,该块将明确地使对象无效。如果异常将导致调用代码放弃损坏的对象,则放弃损坏对象的行为将解决问题。如果调用代码试图使用损坏的对象,则此类尝试应该导致异常,从而迫使进一步展开直到解决问题或者它们完全死亡。 - supercat


正如其他人所说,这取决于。我倾向于在两种情况下使用try / catch / finally块:

  • 我需要以某种方式处理异常,而不仅仅是重新抛出异常。

  • 我需要清理一些资源 finally 块。

除了这两种情况,我让调用代码处理可能发生的任何异常。


1
2017-07-06 13:08



作为旁白, using 基本上是一个 try-finally 阻止清理资源(通过 Dispose)。 - Brian
@Brian - 正确,但不是所有需要清理的东西都会实现IDisposable(或Dispose)。 - Justin Niessner


除了别人说的话,一定要避免这样做:

    try
    {
        throw new ApplicationException("Fake sql ex");
    }
    //catch and do nothing.  swallowing exceptions
    catch(Exception){ }                 

1
2017-07-06 12:59



宠物小精灵异常处理:抓住它们吧! - Pierre-Alain Vigeant


大多数情况下,您不应该捕获异常。有些地方确实有必要捕捉例外情况,例如:

何时可以从该特定异常中恢复。 当您需要记录或报告它时(例如,向用户报告) - 通常在代码的顶层。 当您的代码的调用者无法处理异常时,您需要将它们转换为其他一些错误格式。

此外,using block语句可用于实际调用IDisposable对象上的Dispose,这样就不需要try ... finally。


0
2017-07-06 13:17



如果我想向用户显示消息框“加载数据时出错”怎么办?没有Try Catch块,我将如何实现这一目标? - user279521
你需要一个try-catch来弹出带有异常的消息框 - Dan McClain
正如我所说,你只需要在代码的顶层:“当你需要记录它或报告它时(例如,给用户) - 通常在代码的顶层。” - Polyfun


是什么 Exception 你期待存储过程?提供你不要使用 口袋妖怪异常处理 并确切地知道您的应用程序应该做什么,任何不符合您想要捕获的特定Exception的内容都将被 Application 目的。

换句话说不要使用 catch {} 要么 catch (Exception),但专门的异常处理:

catch(SqlException e)
{
   // Log stacktrace and show a friendly error to your user
}

应用程序错误 事件是应该捕获意外行为的地方,并且比仅仅让客户回复您说“我的字段没有显示任何内容”更容易追踪。


0



预计没有特别的例外,但“只是为了安全”,过去我被告知所有数据库调用都应该包含在try catch块中。 - user279521
但是你不需要捕获异常。您可以愉快地捕获所有SqlExceptions或您正在使用的任何数据库。如果抛出别的东西你可能会想知道它而不是它静静地死 - Chris S


在最内层循环中使用“try catch”,在发生特定异常时应继续执行。请注意,如果你有一个循环执行10,000次并且例如发生异常,例如第十次重复不会影响其他9,990,它可能有助于捕获异常并让循环继续运行。另一方面,如果异常表明故障表明循环中的第11,12,13等等也将失败,那么让异常终止循环比继续重试操作要快得多那是行不通的。


0