C#嵌套的Try-Catch语句或方法?

C#嵌套的Try-Catch语句或方法?,c#,error-handling,methods,C#,Error Handling,Methods,简单的最佳实践问题 您应该嵌套try catch语句还是只使用方法 例如,如果有一个方法可以打开一个文件并关闭该文件,那么在try-catch之外会有open和close,或者更确切地说是finally块中的close 现在,如果您的open方法失败,那么该方法将断言正确吗?那么,您应该将其包装在try-catch块中,还是从另一个方法调用它,而另一个方法又是try-catch块?取决于您尝试执行的操作,但在大多数情况下,嵌套的try/catch是一个过于复杂的函数的标志(或者是一个不太了解异常

简单的最佳实践问题

您应该嵌套try catch语句还是只使用方法

例如,如果有一个方法可以打开一个文件并关闭该文件,那么在try-catch之外会有open和close,或者更确切地说是finally块中的close


现在,如果您的open方法失败,那么该方法将断言正确吗?那么,您应该将其包装在try-catch块中,还是从另一个方法调用它,而另一个方法又是try-catch块?

取决于您尝试执行的操作,但在大多数情况下,嵌套的try/catch是一个过于复杂的函数的标志(或者是一个不太了解异常如何工作的程序员的标志!)


在打开文件的情况下,我会使用IDisposable holder和using子句,因此不需要任何显式的try/catch。

这是一个风格问题,但对我来说,我尝试在一个方法中永远不会有超过一个级别的try/catch/finally嵌套。在进行嵌套尝试时,您几乎肯定违反了1 function=1操作原则,应该使用第二种方法

在打开文件的方法的上下文中,我将使用using语句而不是try-catch。using语句确保在发生异常时调用Dispose

using (FileStream fs = new FileStream(file, FileMode.Open))
{
    //do stuff
}
做与以下相同的事情:

FileStream fs;
try
{
     fs = new FileStream(file, FileMode.Open);
     //do Stuff
 }
 finally
 {
        if(fs!=null)
           fs.Dispose();
 }

大多数时候,我会将嵌套的try/catch块分解为函数。但我有时编写代码来捕获并记录应用程序引发的所有未捕获异常。但是如果日志代码失败怎么办?因此,我还有另一个try/catch方法来防止用户看到默认的.NET未处理异常对话框。但即使是这段代码也可以很容易地重构成函数,而不是嵌套的try/catch块

try
{
    try
    {
        DoEverything(); 
    }
    catch (Exception ex)
    {
        // Log the exception here
    }
}
catch (Exception ex)
{
    // Wow, even the log is broken ...
}

现在我们有了lambdas和类型推断以及其他一些东西,还有一个在其他语言中很常见的习语,它现在在C#中非常有意义。您的示例是打开一个文件,对其执行某些操作,然后关闭它。现在,您可以创建一个helper方法来打开一个文件,并负责确保关闭/处置/清理,但调用为“do stuff”部分提供的lambda。这将帮助您将复杂的try/catch/finally dispose/cleanup内容放在一个地方,然后反复使用

下面是一个例子:

public static void ProcessFile(string filePath, Action<File> fileProcessor)
{
  File openFile = null;

  try
  {
    openFile = File.Open(filePath); // I'm making this up ... point is you are acquiring a resource that needs to be cleaned up after.

    fileProcessor(openFile); 
  }
  finally
  {
    openFile.Close(); // Or dispose, or whatever.
  }
}

如果您有相关的代码,而这些代码不一定属于它自己的单独函数,那又如何呢?那么这是正确的吗

try
{
  // Part 1 Code Here

  try
  {
    // Part 2 Code Here
  }
  catch (Exception ex)
  {
    // Error from Part 2
  }
}
catch (Exception ex) 
{
  // Error from Part 1
} 
//检查开关,如果此时它仍然为零,则可以在此停止程序;否则,将开关设置回零并执行下一个try-catch语句。完全同意如上所述对其进行分解

试一试 { DoChunk2(); //看起来不错。将开关设置为1 } 捕获(例外情况除外) { //在此处记录异常
}

示例代码有助于说明您的问题。是否有用于说明问题的示例代码(更好的真实代码)?关闭,但try/finally代码与使用代码不太匹配。您还需要将其包装在一个匿名作用域块中。如果您的日志记录被破坏,那么您应该让异常传播,以便用户可以投诉您的日志记录被破坏!我仍然可以显示日志代码引发的异常。我只是想这样做,而不是让框架错误窗口出现。我认为,在许多开发人员(如果不是大多数开发人员的话)中,这不会是一个风格问题。这将是一个不理解.NET中异常的问题,并且认为它们需要捕获每个异常,就像Java中一样。在大多数情况下,最好让异常传播。@alhambraeidos,如果我理解正确,是的,你绝对可以。您可以创建一个名为“ForEachLine”的方法,该方法打开文件,执行while循环逐行读取,并调用每行传入的函数??如下所示:Helpers.ForEachLine(@c:\somefile.txt),aLine=>Console.WriteLine(“下一行是:“+aLine”);这会将文件中的所有行输出到控制台,每一行前面都有“下一行是这样说的:,它还可以确保文件正确关闭。@选择Page JekBao可能是因为它没有支持此答案的上下文。简短的说明/代码注释不会有什么坏处。
try
{
  // Part 1 Code Here

  try
  {
    // Part 2 Code Here
  }
  catch (Exception ex)
  {
    // Error from Part 2
  }
}
catch (Exception ex) 
{
  // Error from Part 1
} 
try 
{
  ----
}
catch
{
   try
      {
           ---
      }
   catch
      {
        ---
      }
}
//create a switch here and set it to 0 
try
{
    DoChunk1(); 
    //looks good. set the switch to 1
}
catch (Exception ex)
{
    // Log the exception here
}