那么最好使用try / catch吗?

时间:2013-10-28 15:38:40

标签: c# exception try-catch

什么时候最好使用try和catch?当我使用try和catch(有些甚至-1我......)回答问题时,我得到了愤怒的回答。我用Google搜索并发现了这个article以及此stackoverflow question

我举一些例子:

  1. 我有一个带有time zone IDs的下拉列表,当用户选择他的时区时我正在更新数据库。在其他应用程序中,我从数据库中提取该值并重新计算用户当前时间和日期。可以选择DB中的数据拼写错误(DB或bug中的硬编码更改)。在用户的日期时间的转换方法我正在使用try和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. 有时候我的应用程序中有一部分我正在写一个文件。写入文件可能会导致exeprtion,原因很多,其他一些进程在写入或其他时使用此文件。所以我通常使用这段代码:

     using (StreamWriter w = new StreamWriter(fs))
     {
         try
         {
             w.Write("** (Line) " + someValue + " **" + Environment.NewLine);                       
             w.Flush();                       
         }
         catch(IOExeption ex){}
         finally
         {
             w.Close();   
         }
     }
    
  4. 总之,我看到了一些使用try和catch以及不使用方法的方法。我看到的文章中的一句话说如果发生异常,你需要知道它。,但是在大多数时候处理泛型应用程序时,我知道会发生异常,但大部分都是时间我真的不知道它为什么会发生,所以我以前无法抓住它(就像我写的那些例子),所以什么时候最好使用try和catch

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

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

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

6 个答案:

答案 0 :(得分:3)

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

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

关于您的示例:

在案例1中你可能确实想要防守。但是请确保你在那个阻挡块中做了一些明智的事情。

案例2看起来很合理,但是您正在阅读XML文档只是为了抛弃它。处理它会没有意义吗?

在案例3中,您最后使用try,这与try catch绝对不同。在您的具体示例中,您甚至不需要它,因为使用声明已经确定文件将被关闭。

答案 1 :(得分:1)

从个人的角度来看,我总是认为无论出现什么问题,都会出错,并相应地编写我的异常处理策略。与其他代码有关的主要问题之一就是当你得到一个很容易被困的未处理异常时 - 如果它是生产代码那么它看起来很麻烦,那么它表明你完全不了解你的程序是如何工作的以及可能会发生的事情。错。

我的方法可能有点过分,但如果你正在做的事情会抛出错误,那么它应该被困住。我不是让异常在堆栈中级联并被捕获到顶层的狂热粉丝 - 我更喜欢将它们捕获到源头,记录它们然后,如果应用程序允许它继续,或者最坏的情况下优先失败,让用户(或其他开发人员)了解出了什么问题或原因。

对于Web应用程序,我们使用略有不同的方法。记录错误(堆栈跟踪等),以便授权人员可以看到它,并向用户提供错误的简化版本,告知他们出现了问题但没有详细说明。

无论如何,这是我的两便士。我不确定这种方法是对还是错,但它对我们有用,并帮助我们生成更强大的代码。

答案 2 :(得分:1)

批评你在this answer中使用try / catch并不反对使用try / catch,而是反对使用它的特定方式。

  • 您应捕获异常对象(即使用catch(SomethingHappenedException e),以便获取有关错误的可用信息。

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

看起来似乎有点费劲,但它可以帮助您节省调试时间!

答案 3 :(得分:1)

例如,查看代码会很有帮助。如果没有更具体地了解你正在做什么,就很难评论。

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

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

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

答案 4 :(得分:0)

我想我可以总结一下过去人们在尝试捕捉问题时所遇到的问题,并提供一些可以帮助你的清晰度。

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

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

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

你的try ... catch块也应该封装streamwriter,因为最佳做法是只有一次try ... catch per method。如果使用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 :(得分:0)

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

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