【问题标题】:try catch inside a catch clause在 catch 子句中尝试 catch
【发布时间】:2014-12-22 22:23:30
【问题描述】:

我目前正在以不同的方式加载图像,如下所示:

try {
   // way 1
} 
catch 
{ // way 1 didn't work
   try {
      // way 2
   } 
   catch 
   {
      // etc.
   }
}

我想知道是否有更清洁的方法来做到这一点。目前这不是问题,但如果我添加更多方法,它会变得一团糟。
请注意,加载图像的方法也以相同的方式在 try catch 中,因为它可能不是图像。
它基本上是在尝试一堆东西来弄清楚你拖到应用程序中的是什么。

【问题讨论】:

  • "why" didn't it work? 并处理它是一种更好的设计实践,而不是让某些东西抛出错误并希望你用嵌套的 catch 覆盖它(尤其是对于这样的东西)。尝试加载图像时抛出错误是怎么回事?
  • 我坚信catch 处理程序应该只包含与处理异常相关的代码,仅此而已。如果您需要类似示例中的内容,则应重构代码。
  • 同意@alykins。第一个异常的原因实际上是 exceptional 还是更像是“这个文件没有以正确的签名开始,所以我要尝试另一种可能有效的方法”?跨度>
  • 耶稣...这个地方怎么回事?否决票?

标签: c# try-catch


【解决方案1】:

您可以编写一个接受任意数量的委托的方法,尝试所有委托并在其中一个成功运行后停止。这将异常处理抽象到一个地方,并避免了所有的重复:

public static void AttemptAll(params Action[] actions)
{
    var exceptions = new List<Exception>();
    foreach (var action in actions)
    {
        try
        {
            action();
            return;
        }
        catch (Exception e)
        {
            exceptions.Add(e);
        }
    }
    throw new AggregateException(exceptions);
}

这允许你写:

AttemptAll(Attempt1, Attempt2, Attempt3);

如果方法计算结果,您也可以创建第二个重载来处理它:

public static T AttemptAll<T>(params Func<T>[] actions)
{
    var exceptions = new List<Exception>();
    foreach (var action in actions)
    {
        try
        {
            return action();
        }
        catch (Exception e)
        {
            exceptions.Add(e);
        }
    }
    throw new AggregateException(exceptions);
}

【讨论】:

  • +1 用于在所有操作都失败时聚合并抛出异常。
  • 我真的很喜欢这个解决方案。它干净而清晰。而且,这正是我刚才要找的东西。
【解决方案2】:

假设加载图像的“不同方式”都在失败时抛出异常,您可以迭代不同的方式,直到成功。下面的示例使用Function&lt;Image&gt; 来显示一个在成功时返回图像的无参数函数。在您的具体示例中,您的函数中可能还有参数。

List<Function<Image>> imageLoaders = LoadTheListSomehow();

foreach (var loader in imageLoaders)
{
    try
    {
        var image = loader();
        break;  // We successfully loaded the image
    }
    catch (Exception ex) 
    {
        // Log the exception if desired
    }
}

【讨论】:

    【解决方案3】:

    那里的嵌套看起来确实没有必要。我会将加载图像的每种方式隔离到它自己的私有方法中,然后在循环中将这些方法作为委托调用,如下所示:

    private static MyImage LoadFirstWay(string name) {
        return ...
    }
    private static MyImage LoadSecondWay(string name) {
        return ...
    }
    private static MyImage LoadThirdWay(string name) {
        return ...
    }
    ...
    public MyImage LoadImage(string name) {
        Func<string,MyImage>[] waysToLoad = new Func<string,MyImage>[] {
            LoadFirstWay
        ,   LoadSecondWay
        ,   LoadThirdWay
        };
        foreach (var way in waysToLoad) {
            try {
                return way(name);
            } catch (Exception e) {
                Console.Error("Warning: loading of '{0}' failed, {1}", name, e.Message);
            }
        }
        return null;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-22
      • 1970-01-01
      • 2016-05-08
      • 2015-09-13
      • 2012-02-26
      • 2017-02-13
      • 2010-10-29
      相关资源
      最近更新 更多