The following are effectively the same (in outcome):
catch (Exception e)
{
FunctionA(e);
FunctionB(e);
}
But it's not the same if you do this:
catch (ApplicationException e)
{
FunctionB(e);
}
catch (Exception e)
{
FunctionA(e);
}
This is because FunctionB gets typed to ApplicationException at compile time, wheras the call to FunctionA will always downcast the parameter to Exception. Depending on your implementation of FunctionB, this may not matter, but there are cases where it can make a difference. I would say that as a rule of thumb, if you your method implementation does not need the generic implementation, then don't use it.
Here are some examples of when it would matter:
public T AddSomeContextToThisException<T>(T ex) where T : Exception
{
ex.Data.Add("Some key", "Some context message");
return ex;
}
public T ThisIsABadIdeaForExceptionsButMaybeAGoodIdeaForOtherTypes<T>(T ex) where T : Exception, new()
{
// do something with ex
return new T();
}
The following example needs some additional code for context, so see the code beneath it:
private readonly Bar bar = new Bar();
public void HandExceptionOffToSomethingThatNeedsToBeStronglyTyped<T>(T ex) where T : Exception
{
ICollection<T> exceptions = bar.GetCollectionOfExceptions<T>();
exceptions.Add(ex);
// do other stuff
}
public class Bar
{
// value is object, because .net doesn't have covariance yet
private Dictionary<Type, object> listsOfExceptions = new Dictionary<Type, object>();
public ICollection<T> GetCollectionOfExceptions<T>()
{
if (!listsOfExceptions.ContainsKey(typeof(T)))
{
listsOfExceptions.Add(typeof(T), new List<T>());
}
return listsOfExceptions[typeof(T)] as List<T>;
}
}