8

什么时候最好使用 try and catch?当我使用 try and catch 回答问题时,我得到了愤怒的回应(有些甚至 -1 我......)我用谷歌搜索并找到了这篇文章和这个 stackoverflow问题

我举几个例子:

  1. 我有一个带有时区 ID的下拉列表,当用户选择他的时区时,我正在更新数据库。在其他应用程序中,我从数据库中提取这个值并重新计算用户当前时间和日期。有一个选项是数据库中的数据拼写错误(数据库中的硬编码更改或错误)。在我使用try and catch的用户日期时间的转换方法中,有人告诉我这是错误的!我可以使用 for 循环检查数据库中的值,但每次转换日期时间时都会花费更多......

  2. 我必须使用以下代码声明 XML 文件的格式是否正确:

    protected bool IsValidXML(string xmlFile)
    {
        try
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xmlFile);
        }
        catch(XmlException ex)
        {
            ///write to logger
            return false;
        }
        return true;
    }
    

    我看不到任何其他方法来检查 xml 文件。

  3. 有时我在我的应用程序中有一部分正在写入文件。写入文件可能会由于多种原因导致执行,其他一些进程在写入或其他时正在使用该文件。所以通常我使用这个代码:

     using (StreamWriter w = new StreamWriter(fs))
     {
         try
         {
             w.Write("** (Line) " + someValue + " **" + Environment.NewLine);                       
             w.Flush();                       
         }
         catch(IOExeption ex){}
         finally
         {
             w.Close();   
         }
     }
    

总之,我看到了一些使用 try 和 catch 的方法以及不使用的方法。我看到的文章中的一句话说如果发生异常,你需要知道它。,但是在处理通用应用程序时,大多数时候我知道会发生异常,但大多数时候我真的不知道为什么会发生,所以我之前无法捕捉到它(就像我写的例子一样),所以什么时候最好使用 try and catch

在 ASP.NET 的同一级别中,页面有一个错误事件,您可以像这样捕获它:

this.Error += new EventHandler(Page_Error); //this = instance of System.Web.UI.Page

事件是否与try catch问题相同?

4

6 回答 6

4

如何处理异常取决于异常的性质以及发生的上下文。

聪明的人写了关于这个主题的优秀文章,我当然可以推荐:

关于你的例子:

在案例 1 中,您可能确实想要进行防御。但是然后确保你在那个 catch 块中做一些明智的事情。

案例 2 看起来很合理,但是您阅读 XML 文档只是为了把它扔掉。处理它会不会更有意义?

在案例 3 中,您使用的是 try finally,这与 try catch 绝对不是一回事。在您的特定示例中,您甚至不需要它,因为 using 语句已经确保文件将被关闭。

于 2013-10-28T16:13:32.717 回答
1

从个人角度来看,我一直认为任何可能出错的地方都会出错,并相应地编写我的异常处理策略。我对其他代码的主要问题之一是当您遇到一个很容易被捕获的未处理异常时 - 它看起来很混乱,如果它是生产代码,那么它表明您完全不了解您的程序如何工作以及可能发生的事情错误的。

我的方法可能有点矫枉过正,但如果你正在做的事情可能会引发错误,那么它应该被困住。我不喜欢让异常通过堆栈级联并在顶层被捕获 - 我更愿意在源头捕获它们,记录它们,然后,如果应用程序允许它继续,或者最坏的情况是优雅地失败并且让用户(或其他开发人员)了解问题所在或原因。

对于 Web 应用程序,我们使用稍微不同的方法。错误(堆栈跟踪等)被记录下来,以便授权人员可以看到它,并为用户提供错误的简化版本,告诉他们出了什么问题,但不是细节。

反正那是我的两便士。我不确定这种方法是对还是错,但它对我们有用,可以帮助我们生成更健壮的代码。

于 2013-10-28T15:47:46.920 回答
1

对您在此答案中使用 try/catch 的批评并不是反对一般使用 try/catch,而是反对使用它的特定方式。

  • 您应该捕获异常对象(即使用 catch(SomethingHappenedException e) 以便获得有关问题所在的可用信息。

  • 您应该捕获特定的异常而不是一切。在 DateTime 示例中,我将尝试找出我的每个调用可能引发的异常。然后我会尝试找出是否有某种方法可以在不使用异常的情况下捕获这些错误 - 可能在该代码中捕获的异常之一是 ArgumentNullException。这是一个例外,但我应该能够通过首先检查我没有传递空区域 ID 来在流程中处理它。
    最后,如果无法在程序的正常流程中处理这些情况,我会捕获可能发生的特定异常,并尽可能靠近异常源。

这似乎需要更多的努力,但它确实为您节省了调试时间!

于 2013-10-28T15:57:12.047 回答
1

例如1,看代码会很有帮助。如果没有对你在做什么的更具体的想法,很难发表评论。

例如 2,该代码的问题在于它完全隐藏了任何错误情况。当然,我们会发现一个 xml 文件是好是坏……但是为什么xml 是好还是坏呢?我们无法知道。并不是 try/catch 不好:而是整个事情都写错了。只需编写代码来读取 xml 文件,并围绕该代码进行错误处理。

例如 3,您再次吞下了任何有用的异常信息,实际上根本没有对您的 try/catch做任何事情。块中的.Close()调用finally是完全不必要的,因为当流被using块处理时,关闭流是完全处理的。

总之,我认为你需要在这里学习的并不是 try/catch 块不好。吞下异常信息是不好的

于 2013-10-28T15:58:52.770 回答
0

我想我可以用你关于 try...catch 的问题来总结人们过去遇到的问题,并提供一些对你未来有帮助的清晰度。

您的前两个示例是由数据验证错误引起的。在将数据传递给转换函数(示例 1)或尝试写入 XML 文件(示例 2)之前,应检查数据是否存在已知的验证错误。

异常处理有很大的开销,所以它应该只在绝对必要时发生。try...catch 模式旨在处理意外(异常)错误,而不是标准数据验证。

示例 3 几乎是正确的用法。在这种情况下,可能会发生您无法准备的意外情况,例如 IOException。捕获特定异常被认为是错误的形式,因为它可能导致多个捕获块或错过处理。捕获泛型 Exception 对象比较好,异常处理代码可以确定并处理确切的异常类型。

您的 try...catch 块也应该封装 streamwriter,因为最佳实践是每个方法只有一个 try...catch。如果您使用 try...catch,它必须始终包含异常处理代码。空的 catch 块或空的 finalize 块是不好的形式,对代码或任何试图在你之后维护它的人没有帮助。

    try
    {
       using (StreamWriter w = new StreamWriter(fs))
       {

           w.Write("** (Line) " + someValue + " **" + Environment.NewLine);                       
           w.Flush();                       
       }
    }
    catch(Exception ex)
    {
        //exception handling code here
    }
    finally
    {
       //any clean up code here. The using statement makes it unnecessary for the streamwriter
    }

希望所有这些都有助于回答一些问题并使问题更加清晰。

于 2013-10-28T15:58:35.887 回答
0

根据我的经验,任何外部操作(例如与数据库或文件系统交互,或使用 3rd 方组件)都应该有一个 try catch 块。在我自己的代码中,我总是尝试将保护子句放入方法中以限制我自己的代码产生的异常数量,例如,如果您知道数据库不会接受一个人对象上的空名字,请添加一个保护子句应添加到任何保存方法的顶部。

简而言之,不要依赖异常来告诉你代码哪里出错了,而是首先尝试减少异常的可能性

于 2013-10-28T16:09:01.777 回答