C# try-catch和finally-block的执行顺序

C# try-catch和finally-block的执行顺序,c#,C#,我对尝试、捕获和最终阻止执行的顺序有很大的混乱 我还想知道什么时候应该使用try-catch块,我应该在try-catch块中放置什么,我还想知道try块中是否出现了异常,如果采取了与try块对应的操作,那么首先执行哪个catch还是最后执行哪个 始终要执行),并且在执行这两个操作之后,控制会返回到try块,或者永远放弃它。您几乎不应该使用try/catch 您应该只捕获实际上可以纠正的异常,并且只有在您预期的情况下。否则,让调用者来处理异常——或者不处理 如果使用,将首先执行任何catch子句

我对尝试、捕获和最终阻止执行的顺序有很大的混乱

我还想知道什么时候应该使用try-catch块,我应该在try-catch块中放置什么,我还想知道try块中是否出现了异常,如果采取了与try块对应的操作,那么首先执行哪个catch还是最后执行哪个
始终要执行),并且在执行这两个操作之后,控制会返回到try块,或者永远放弃它。

您几乎不应该使用try/catch

您应该只捕获实际上可以纠正的异常,并且只有在您预期的情况下。否则,让调用者来处理异常——或者不处理

如果使用,将首先执行任何
catch
子句-仅其中一个

然后,
finally
被“finally”执行


这在很多地方都有更好的表述,但我会尝试。以下代码:

try
{
    // Do something here
}
catch (Exception ex)
{
    MessageBox.Show("Friendly error message");
}
不修复异常。它隐藏了异常,因此问题永远不会得到解决。该代码不知道抛出了哪个异常,因为它将捕获所有异常,并且它对纠正问题没有任何作用——它只是告诉用户一个错误

事实上,上述代码应替换为以下代码:

// Do something here
这样,如果此方法的调用方知道如何修复特定问题,则调用方可以修复这些问题。您不会从调用者中删除该选项

如果调用方不知道如何解决问题,那么调用方也不应该捕获异常


下面是一个以合理方式使用异常的示例(来自MSDN)。这是本文档中示例的修改形式


请注意,此代码使用try/catch来包围一小段代码。在该try/catch块中,如果抛出SmtpException或SMTPFailedRecipientSexException,我们知道如何处理它。例如,如果我们要捕获
IOException
,我们就不知道它意味着什么,也不知道该怎么做。任何你实际上不知道如何纠正的异常都不应该被捕获,除了可能向异常添加信息、记录它并重试之外。

A
试试。。。catch
块用于捕获异常。在
try
块中,您输入了可能引发异常的代码

如果未发生异常,则
try
块中的代码按预期完成。如果有一个
finally
块,那么接下来将执行该块

如果发生异常,则执行跳转到第一个匹配的
catch
块的开始。代码完成后,将执行finally块(如果存在)。执行不会返回到
try
块。

如果您有(注意:这是无效的C#,请参阅下面的有效示例):

代码A将被执行。如果一切顺利(即A执行时没有抛出异常),它将转到最后,因此代码C将被执行。如果在执行A时引发异常,那么它将转到B,最后转到C

例如,以下是一个有效的C代码块:

使用try/catch/finally的原因是为了防止程序在某些代码中出错时失败(在上面的示例中为A)。如果出现问题,您可以使用
catch
part来捕获问题并执行一些有用的操作,例如通知用户、将异常记录到日志文件中、重试或尝试其他您认为可能有效的操作,而不是最初尝试的操作

最后
用于确保执行某些清理。例如,在一个应用程序中,您可以尝试打开一个文件并读取它。如果打开成功,但读取失败,您将有一个打开的文件悬空。在这种情况下,您希望将其关闭,这将在
finally
块中执行-始终执行此块,确保文件关闭

请查看此处以了解更多信息:

    • 以下是一个示例:

      try
      {
          someFunctionThatWorks();
      
          functionThatThrowsAnException(); // As soon as this function throws an exception we are taken to the catch block
      
          anotherFunction();  // <-- This line will never get executed
      }
      catch(Exception e)
      {
          // Here you can handle the exception, if you don't know how to handle it you should not be catching it
          // After this you will not be taken back to the try block, you will go right to the finally block
      }
      finally
      {
          // Code here is always executed at the very end, regardless of whether an exception was thrown or not
      }
      
      试试看
      {
      一些有效的函数();
      函数ThrowsanException();//一旦此函数引发异常,我们将被带到catch块
      
      anotherFunction();//请学习使用句号(
      )和问号(
      )恰当地说。我无法理解你的问题,因为它目前的状况。微软解释的规范-我现在更困惑了,先生,为什么我不应该使用try-catch块?如果我事先知道异常会出现在哪里,那么我已经纠正了。这也是你的声明的意思吗“让调用者处理异常-或者不处理。"如果你不明白自己在做什么,那就试着听。不要使用它。别管异常。如果你的代码抛出了一个不应该抛出的异常,那么就修复你的代码。对于大多数开发人员来说,几乎没有理由捕捉异常。John,我认为尝试在
      cat中执行代码是一个非常糟糕的主意ch
      block?您正在运行对
      Send()的循环调用
      。如果失败,那里会捕获什么异常?什么都没有。为什么要捕获那里的异常?不。捕获异常的目的是重试。如果重试失败,放弃。先生,如果finally本身抛出一些异常,那么会发生什么?如果finally块中抛出另一个异常,您可以通过嵌套另一个try…catch…最后,否则它将充当任何其他未处理的异常。看看这个,先生,在“用户定义的条件”上抛出的异常是什么意思?我不确定我理解你所说的“用户定义的条件”是什么意思-如果您指的是用户定义的异常,请参见此处:。当系统定义的任何异常都没有为您提供要发出信号的错误的适当解释时,将使用用户定义的异常。-1
      try {
         // ... some code: A
      } catch(...) {
         // ... exception code: B
      } finally {
         // finally code: C
      }
      
      public class EHClass
      {
          void ReadFile(int index)
          {
              // To run this code, substitute a valid path from your local machine
              string path = @"c:\users\public\test.txt";
              System.IO.StreamReader file = new System.IO.StreamReader(path);
              char[] buffer = new char[10];
              try
              {
                  file.ReadBlock(buffer, index, buffer.Length);
              }
              catch (System.IO.IOException e)
              {
                  Console.WriteLine("Error reading from {0}. Message = {1}", path, e.Message);
              }
              finally
              {
                  if (file != null)
                  {
                      file.Close();
                  }
              }
              // Do something with buffer...
          }
      }
      
      try
      {
          someFunctionThatWorks();
      
          functionThatThrowsAnException(); // As soon as this function throws an exception we are taken to the catch block
      
          anotherFunction();  // <-- This line will never get executed
      }
      catch(Exception e)
      {
          // Here you can handle the exception, if you don't know how to handle it you should not be catching it
          // After this you will not be taken back to the try block, you will go right to the finally block
      }
      finally
      {
          // Code here is always executed at the very end, regardless of whether an exception was thrown or not
      }