【问题标题】:So is it best to use try/catch? [closed]那么最好使用 try/catch 吗? [关闭]
【发布时间】:2013-11-07 11:24:51
【问题描述】:

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

我举几个例子:

  1. 我有一个带有time zone IDs 的下拉列表,当用户选择他的时区时,我正在更新数据库。在其他应用程序中,我从数据库中提取这个值并重新计算用户当前时间和日期。有一个选项是数据库中的数据拼写错误(数据库中的硬编码更改或错误)。在我使用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问题相同??

【问题讨论】:

  • 什么问题?因为这真的取决于手头的问题。
  • @BoltClock 那-1 answer is here 是投反对票的人。
  • @SriramSakthivel - 你看,这就是我爱你的原因,你是坚持
  • @Servy - 我每天都在尝试获得程序员的意见。
  • @Izikon 这不是 SO 的用途。基于高度意见的问题不太适合本网站的格式,因此是不允许的。

标签: c# exception try-catch


【解决方案1】:

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

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

关于你的例子:

在第 1 种情况下,您可能确实想要采取防御措施。但是,请确保您在那个 catch 块中做一些明智的事情。

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

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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • 我在文章和其他地方读到过有关进食或吞咽异常的信息。我知道这可能是一种糟糕的饮食习惯,但你和这篇文章所说的吃或吞咽是什么意思?
    • 吞下异常意味着捕获它,然后忽略异常或堆栈跟踪中的任何信息。那很糟。如果您想吞下异常,则很可能您在错误的级别上处理了错误。上去,把 try/catch 放在你调用当前函数的地方。
    • 所以如果我在示例 2 中使用只捕获不捕获(IOExeption)更好?
    • 没有。回到更高层次的抓捕原则。您希望将异常处理移动到您的函数的调用站点。在这种情况下,这似乎没有任何意义,因为它完全使该方法无效。发生这种情况时,您在错误的位置进行错误检查。 只需尝试解析文件,而不是使用单独的方法来检查 xml 是否格式正确。在读取文件时,让格式正确错误的错误处理与其他类型错误的错误处理放在同一位置。
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      我想我可以用你关于 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
          }
      

      希望所有这些都有助于回答一些问题并澄清问题。

      【讨论】:

        【解决方案5】:

        this answer 中对您使用 try/catch 的批评并不是针对一般使用 try/catch,而是针对特定的使用方式。

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

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

        这似乎有点费力,但它确实为您节省了调试时间!

        【讨论】:

          【解决方案6】:

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

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

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

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

          【讨论】:

          • 唯一的例外(哈哈)我对这种方法的唯一例外是有时允许通过代码弹出异常是可以接受的。在这些情况下,我认为没有理由创建级联的 catch/rethrow 链。
          • 我不完全同意这个答案。不要在对它们无能为力的代码中捕获异常。它们应该冒泡到可以适当处理的地方,可以通过优雅的失败或重试或其他方式。当然,也许你的意思是我误解了。
          • 我想我不同意你的不同意见!如果例如在我的数据层中引发错误,我想将其捕获在那里。诚然,我对此无能为力,但我需要数据对象的状态以进行详细记录,一旦离开方法就会消失。
          猜你喜欢
          • 2012-11-25
          • 2016-05-27
          • 1970-01-01
          • 1970-01-01
          • 2011-06-24
          • 2013-10-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多