C# 中异常管理器控制流的可扩展方法?

Scalable approach for control flow of exception manager in C#?

如果嵌套的 try-catch 数量恰好很多,例如a 100,除了简单地按以下方式编写 100 个嵌套的 try-catch 之外,还有其他方法吗?

  try{ 
    ....
    } catch(exception ex1)
    try{ 
    ....
    } catch(exception ex2) {
        try{
           }
     ....

如果需要,您可以自由嵌套 try/catches 多层。

try 
{
   operation1();
}
catch (Exception e)
{
   try
   {
     operation2();
   }
   catch (Exception e2)
   {
      // etc
   }
}

只需在 catch 块中再写一个 try 块。

try {
  //task A
} catch(Exception ex) {
  try {
    //task B
  }
}

嵌套的 try-catch 会占用大量资源,如果失控,它们会显着降低程序的性能。但是,您可以按顺序添加 catch 块:

try  
{
    //code here
}catch(SomeException ex)
{
    //Display what the specific exception was
}catch(SomeOtherException ex)
{
    //Display what the specific exception was
}

另一种选择是将您的任务转移到 return 一个 bool 表示成功的方法,然后您就不必嵌套 try/catches:

public static bool TrySomething(string someInput)
{
    bool result = true;

    try
    {
        // do something with someInput
    }
    catch
    {
        result = false;
    }

    return result;
}

public static bool TrySomethingElse(string someInput)
{
    bool result = true;

    try
    {
        // do something with someInput
    }
    catch
    {
        result = false;
    }

    return result;
}

然后在你的主要代码中,你可以这样做:

string data = "some data";

if (!TrySomething(data))
{
    TrySomethingElse(data);
}

鉴于您需要执行此操作 100 次并且必须对控制流使用异常(如果可能应避免)。你可以使用一些包装器,像这样:

public class ExWrapper
{
    private readonly Action _action;
    private readonly ExWrapper _prev;

    private ExWrapper(Action action, ExWrapper prev = null)
    {
        _action = action;
        _prev = prev;
    }

    public static ExWrapper First(Action test)
    {
        return new ExWrapper(test);
    }

    public ExWrapper Then(Action test)
    {
        return new ExWrapper(test, this);
    }

    public void Execute()
    {
        if (_prev != null)
            try
            {
                _prev.Execute();
            }
            catch (Exception)
            {
                _action();
            }
        else
            _action();
    }
}

这允许您链接操作,其中仅当第一个操作抛出时才执行下一个操作。您可以在以下示例中使用它:

ExWrapper.First(() => { Console.WriteLine("First");   throw new Exception(); })
         .Then( () => { Console.WriteLine("Second");  throw new Exception(); })
         .Then( () => { Console.WriteLine("Third");   throw new Exception(); })
         .Then( () => { Console.WriteLine("Fourth"); })
         .Execute();

这会按给定顺序执行所有操作或 lambda,但只有在第一个抛出时才会执行后续操作。上面的例子打印:

First
Second
Third
Fourth

如果删除示例中的 throws

ExWrapper.First(() => { Console.WriteLine("First");  })
         .Then( () => { Console.WriteLine("Second"); })
         .Then( () => { Console.WriteLine("Third");  })
         .Then( () => { Console.WriteLine("Fourth"); })
         .Execute();

只执行了第一个动作,结果输出如下:

First