抛出并捕获异常后继续执行代码

时间:2010-06-09 16:01:46

标签: c# exception exception-handling

抛出异常后如何恢复代码执行?

例如,请使用以下代码:

namespace ConsoleApplication1
{
    public class Test
    {
        public void s()
        {
            throw new NotSupportedException();
            string @class = "" ;
            Console.WriteLine(@class);
            Console.ReadLine();
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            try
            {
                new Test().s();
            }
            catch (ArgumentException x)
            {
            }
            catch (Exception ex)
            {
            }
        }
    }
}

在单步执行时捕获异常后,程序将停止运行。我怎么还能继续执行?

编辑:我特别指的是Console.WriteLine(@class);似乎没有被击中,因为当我在调试模式下运行它时,程序退出调试模式。我想跑到这条线上并停下来。

由于

10 个答案:

答案 0 :(得分:32)

好吧,catch块之后没有任何代码,所以程序会停止运行。不确定你要做什么。

以下内容应证明该程序不会在catch块之后“停止”。如果有要执行的代码,它将在catch块之后执行代码:

static void Main(string[] args)
{
    try
    {
        new Test().s();
    }
    catch (ArgumentException x)
    {
        Console.WriteLine("ArgumentException caught!");
    }
    catch (Exception ex) 
    { 
        Console.WriteLine("Exception caught!");
    }

    Console.WriteLine("I am some code that's running after the exception!");
}

代码将根据捕获的异常打印相应的字符串。然后,它会在最后打印I am some code that's running after the exception!

<强>更新

在您的编辑中,您问为什么Console.WriteLine(@class);似乎没有被点击。原因是您明确地s()方法的第一行中抛出异常;任何后续内容都会被忽略。遇到异常时,执行停止,异常在调用堆栈中向上传播,直到相应的处理程序可以处理它(这可能是catch块,对应于包含有问题语句的try在同一个方法中,或者它可能是调用堆栈中的catch块。如果找不到合适的处理程序,程序将以堆栈跟踪终止[至少在Java中 - 不确定是否发生相同的情况C#])。

如果你想点击Console.WriteLine行,那么你不应该在方法的开头显式抛出异常。

答案 1 :(得分:8)

听起来你想要可恢复的例外。 C#没有做可恢复的异常,我怀疑CLR是否支持它们。

抛出异常的目的是在调用环境中的某些内容(参数,对象状态,全局状态)使函数的操作无法或无效时,中止函数和整个操作(调用堆栈)。例如,将零参数传递给需要通过该参数划分数量的函数。除以零将不会产生有意义的结果,如果这是函数的唯一目的,那么函数也不能返回有意义的结果。所以,抛出异常。这将导致执行跳转到最近的catch或最终阻塞调用堆栈。没有返回抛出异常的函数。

如果要在调试器中单步执行代码以跟踪Console.WriteLine()调用,则需要从代码中删除抛出新的NotSupportedException()行并重新编译。

答案 2 :(得分:7)

如果您担心方法中会抛出异常但希望方法继续,请在方法中添加错误处理程序。

class Test 
{ 
    public void s() 
    { 
        try
          {
              // Code that may throw an exception
              throw new NotSupportedException();
          } 
          catch(Exception ex)
          {
              // Handle the exception - log?, reset some values?
          }
          string @class = "" ; 
          Console.WriteLine(@class); 
          Console.ReadLine(); 
    } 
} 

您还可以返回一个bool或其他值来表示状态。

答案 3 :(得分:3)

免责声明:我并不是说你实际上是这样做的。

您可以使用以下代码模仿旧的VB样式On Error Resume Next。

public static class ControlFlow
{
  public static Exception ResumeOnError(Action action)
  {
    try
    {
      action();
      return null;
    }
    catch (Exception caught)
    { 
      return caught;
    }
  }
}

然后它可以像下面一样使用。

public static void Main()
{
  ControlFlow.ResumeOnError(() => { throw new NotSupportedException(); });
  ControlFlow.ResumeOnError(() => { Console.WriteLine(); });
  ControlFlow.ResumeOnError(() => { Console.ReadLine(); });
}

答案 4 :(得分:1)

我将一些简单的代码放在一起以捕获在catch块中抛出的异常:

try
{
    //do code here
}
catch (Exception ex)
{
    try { SomeMethod1(); }
    catch { }

    try { SomeMethod2(); }
    catch { }

    try { SomeMethod3(); }
    catch { }
}
finally
{
    //cleanup goes here
}

答案 5 :(得分:0)

执行仍在继续,但在捕获异常后没有代码。如果你想重复调用s,那么考虑在while循环中包装try / catch块。

答案 6 :(得分:0)

程序停止运行,因为在Main()方法中没有以下代码要执行!您可以在代码中添加以下行,以使程序保持运行,直到有控制台输入:

Console.ReadLine();

答案 7 :(得分:0)

对于该代码,您不能。如果将任务分解为较小的块,则可以在下一个块中恢复。但通常情况下,使用与异常不同的机制报告非致命错误更容易,例如返回是否继续的回调函数。

答案 8 :(得分:0)

您可以在调试中使用“步进”功能来实现每次运行。

答案 9 :(得分:-5)

public static void Main()
{
    for (int j = 0; j <= 100000; j++)
    {
        try
        {
                // TODO: Application logic...
        }
        catch
        {
                System.Threading.Thread.Sleep(1000);
        }
    }
}