尝试在catch子句中捕获

时间:2014-10-27 16:52:53

标签: c# try-catch

我目前正以不同的方式加载图片:

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

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

3 个答案:

答案 0 :(得分:9)

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

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 :(得分:1)

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

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
    }
}

答案 2 :(得分:1)

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

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;
}