'Retry' mechanism with callback We've had a situation whereby we have to cater for certain exceptions and retry a particular method whenever these exceptions occur. This is required in various parts of the system. In addition, we (might) want to invoke a 'callback' upon the need to retry.

I'll show you the code, then give you an example of useage:

    public static void InvokeActionWithRetry(Action action, int retryAttempts, Action retryCallback = null, params Type[] exceptionTypes)
    {
        do
        {
            try {
                action();
                break;
            }
            catch (Exception ex)
            {
                   if ((exceptionTypes?.Length &gt; 0 &amp;&amp; exceptionTypes.Contains(ex.GetType()))
                        || retryAttempts == 0)
                    throw;

                if (retryCallback != null)
                    retryCallback();
            }

            retryAttempts--;
        }
        while (retryAttempts &gt;= 0);
    }


So, an example (although not a real-world one), may be:

ActionHelper.InvokeActionWithRetry(() =&gt; {
    Print(document);
},
5,
() =&gt; {
    RebootPrinter();
},
typeof(PrinterNeedsRestartException));


Is there anything that can be improved with the static method I've written?

I'm pretty new to using actions/funcs so I'm open to suggestions about how I can refactor this.

I also feel the type evaluation is a little 'hacky'.

EDIT:

I just noticed I'm not checking the types collection passed in prior to calling Contains on it. Naughty. I'll rework that bit and update the question.
Consider this example:

InvokeActionWithRetry(() =&gt; 
        { 
            Console.WriteLine("action"); 
            throw new Exception(); 
        }, 
    3);


It prints 'action' four times. That's not what I expect from the API (but is what I expected from reading the code). I'd expect the number I pass in to be the total number of invocations - not the number of retries after the first attempt.



You need to check this arguments for this method as there is a lot of scope to pass in the weird values. e.g. what if retryAttempts is a negative number? That doesn't make sense!

You also need to check action for null.