我应该多久使用一下C#中的try和catch?

时间:2009-02-02 23:43:15

标签: c#

在编写#1优先级为永不崩溃的C#应用​​程序时,我应该多久使用一次try-catch块?

我可以在try-catch块中的方法中封装所有语句吗?

public void SomeMethod()
{
    try
    {
        // entire contents of the function
        // library calls
        // function calls
        // variable initialization .. etc
    }
    catch (Exception e)
    {
        // recover
    }
}

将所有内容包装在try-catch块中有什么缺点?

13 个答案:

答案 0 :(得分:31)

唯一的缺点是实际抛出异常。包装代码没有开销,除非发生异常。

此外,您不希望将try / catch用于控制流。考虑这个(错误的代码):

try {

    FileStream fs = File.Open("somefile.txt", FileMode.Open);

} catch (Exception ex) {
    MessageBox.Show("The file does not exist. Please select another file");
}

你会从File.Exists这样的东西中获得更多性能。如:

if(!File.Exists("somefile.txt"))
  MessageBox.Show("The file does not exist.")

编辑: 找到MSDN direct quote

  

寻找和设计   异常繁重的代码可能导致a   体面的胜利。请记住这一点   这与try / catch无关   块:你只会产生成本   抛出实际异常。您   可以使用尽可能多的try / catch块   你要。使用例外   无偿的是你失败的地方   性能。例如,你应该   远离使用的东西   控制流程的例外。

答案 1 :(得分:24)

这是一个很大的话题。开始here,以便对异常处理最佳实践进行一些出色的讨论,并为宗教战争做好准备......

Code Analysis Team Blog

Martin Fowler - Fail Fast

MSDN on Exception Handling

Checked vs Unchecked Exceptions

我自己的观点是,大多数情况下你使用“尝试/终结”很多,但“抓住”很少。问题是,如果您尝试在错误的实例中捕获并处理异常,则可能会无意中将应用程序置于错误状态。通常,使用dev和test来了解实际需要处理异常的位置。那些将是你无法检查的地方。即你不应该真正需要处理null引用或filenotfound因为你可以主动检查那些。只有您知道的例外情况可能会发生,但您无法做任何事情。除此之外,为了您的数据状态,让它崩溃。

如果您吞咽异常,通常意味着您不了解您的计划或您获得例外的原因。捕获System.Exception是代码味道的典型代表......

答案 2 :(得分:8)

实际上,除了记录之外,我很少使用catch块。 finally对我来说更为常见。大多数情况下,lockusing会做我可以做的所有事情(事实上,这也是finally)。

Eric Lippert有blog entry on exceptions可能有用。

答案 3 :(得分:4)

通常IMO最好在try catch中放置不受控制的较小块。如果你说:

try
{
   //anything that could possibly go wrong
   //This kind of thing is only good for Logging IMO and could be done in
   //Global.asax
}

你怎么可能知道你的捕捉方法该怎么做因为它可能是任何东西......

要好得多:

try
{
   //divide user imputs
}
catch(DivideByZeroException)
{
  // tell user bad inputs ect....
}
catch (Exception e)
{
    //If you choose to throw the exception you should
    //***********************
    throw; 
    //VS
    throw ex; //Throw ex will restart the stack trace  
    // recover
}
finally
{
    //Clean up resources and continue
}

最终总是在运行

答案 4 :(得分:3)

这个问题的关键是以下几行:

// recover

为了能够恢复,你必须知道恢复的内容和方法。而且这是假设它有可能恢复,这通常不是。

当您知道如何处理异常,当您知道如何从中恢复异常以及确定可以时,您应该只使用catch的{​​{1}}部分来吞下异常在不使应用程序处于不一致或无效状态的情况下这样做。

如果您可以对应用程序中所有方法调用中的所有可能异常执行此操作,那么请继续操作,否则您可能需要重新考虑您的#1优先级(有时快速失败是比尝试保留应用程序更好的选择当出现问题时会生存,并且稍后会更难调试崩溃。)

答案 5 :(得分:2)

如果你能有意义地处理它,你应该只捕获并停止异常而不重新抛出它。否则它是一个错误,它应该传播。

我认为当他们说“这个应用程序永远不会崩溃”时,隐含要求它的行为正确。只有停止有意义处理的异常才能满足行为正确的要求。

通常,应用程序将有一个顶级catch块来捕获和记录未处理的异常。这些应该不经常发生(也许你的要求可能被解释为意味着这些根本不应该发生)。如果您在代码中的任何其他位置捕获并停止异常,则可能无法发现这些问题。如果您捕获日志并停止代码的许多其他部分,那么从关注点分离的角度来看,您的应用程序构建得很糟糕。

答案 6 :(得分:1)

try块有性能开销,如果这样做,你的整个函数运行速度会慢于其他情况。 catch (Exception e)也是一个坏主意,如果你发现你想要对你抓到的东西做一些有用的事情,如果你抓住所有例外,就不可能知道你应该做什么。

答案 7 :(得分:1)

你可以这样做,虽然几乎在你正在运行的任何给定环境中,但是有一个全局异常处理程序,你可以捕获并处理未知的错误。

对于Web应用程序,有一个Global.asax,对于一个控制台程序,只需将您的Main()包装在try / catch中,对于服务,有AppDomain.CurrentDomain.UnhandledException等。

您应该在可以预测更具体块中的异常的部分中进行封装,但是全局异常处理程序应该大大简化您的代码并帮助您。

答案 8 :(得分:1)

我试图通常避免使用</r>块。我更喜欢使用循环来强制用户遵守应用程序的规则。例如,如果用户只应输入等于或小于int的int,我会使用:

try catch

而不是使用:

if (input > x)
{
     Console.WriteLine("Invalid input. Please enter a number that is equal to or less than x.");
{...}
}

根据我个人的经验,我发现编写起来比较容易,因为可以避免将代码封装在try块中(保护代码)。

当然,总会有时候使用try catch是不可避免的 - 我只是想在可能的情况下解决它。

答案 9 :(得分:0)

我们当前的应用程序有类似的任务:永不崩溃。永远优雅地退出。要做到这一点,你必须确保每一行代码都包含在try-catch块中,或者只能通过代码调用它的例外情况可以冒出来。

另外,为了防止未捕获的异常,我们将UnhandledExceptionEventHandler附加到AppDomain.CurrentDomain。

答案 10 :(得分:-1)

您应该在一段代码抛出异常的任何时候使用它们。

你必须要小心,抓住一般例外永远不是一个好主意。您必须决定要处理它们的图层。

意味着你越深,你想要抓住非常具体的兴奋并且更加普遍。在数据库中捕获SqlException。当你在堆栈中走得更高时,你会发现更多的异常,最终在最顶端捕获一般异常。

通过这种方式,您可以根据具体情况处理每个异常。一般情况下你不会知道如何处理。

答案 11 :(得分:-1)

public void functionName  
{
  try
  {
     //your codes
     //sometimes 'return' shows exceptions
  }
  catch(Exception e)
  {
    messagebox.show(e.Tostring());   //to know what is the exception
  }
  finally
  {
  }
}

答案 12 :(得分:-3)

尝试捕获c#:

try{

}
catch (NullReferenceException en)
{

}