1

I'm currently loading images in different ways like this:

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

I was wondering if there was a cleaner way to do this. Currently it's not a problem but if i add a few more ways it's going to get messy.
Note that the method loading the image is also in a try catch in the same way because it might not be an image.
It's basically trying a bunch of stuff to figure out what it is you dragged into the application.

10
  • 1
    "why" didn't it work? and handling that is a better design practice rather than letting something throw an error and hoping you cover it with nested catches (especially for something like this). What is happening that you are throwing errors trying to load the image? Commented Oct 27, 2014 at 16:55
  • 2
    stackoverflow.com/questions/7796420/… Commented Oct 27, 2014 at 16:55
  • 4
    I'm a firm believer in catch handlers should only contain code relevant to handling the exception, and nothing more. If you have a need for something like in your example, you should restructure the code. Commented Oct 27, 2014 at 16:57
  • 1
    Agreed with @alykins. Is the reason for the first exception something that's actually exceptional or is it more like "this file doesn't start with the right signature so I'm going to try another method that might work"? Commented Oct 27, 2014 at 16:58
  • 1
    Jesus...what is going on with this place? Downvotes? Commented Oct 27, 2014 at 17:02

3 Answers 3

9

You can write a method that accepts any number of delegates, attempting all of them and stopping after one of them runs successfully. This abstracts the exception handling into one place, and avoids all of the repetition:

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

This allows you to write:

AttemptAll(Attempt1, Attempt2, Attempt3); 

If the methods compute a result you can create a second overload to handle that as well:

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); } 
Sign up to request clarification or add additional context in comments.

2 Comments

+1 for aggregating and throwing the exceptions if all actions fail.
I really like this solution. It's clean and clear. Also, it's what I was looking for just now.
1

Assuming the "different ways" to load the image all throw an exception upon failure, you could iterate through the different ways, until one succeeds. The example below uses a Function<Image> to show a parameterless function that returns an image upon success. In your concrete example, you probably also have parameters into your function.

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

Comments

1

The nesting there does look unnecessary. I would isolate each way of loading an image into its own private method, and then called these methods as delegates in a loop, like this:

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.