Search code examples
c#.netdelegatesactionfunc

Combining Action and Func in one parameter


I have many methods that require some logging with the same pattern. Some methods need to return some value, some don't. I have created a method with Action parameter to avoid copypasting all of the logic. It looks like this:

private void Execute(Action action)
{
   Logger.Start();
   try
   {
      action();
   }
   catch(Exception exception)
   {
      Logger.WriteException();
      throw;
   }
   finally
   {
       Logger.Finish();
   }
}

Now I have some calls that like that

public void DoSomething(string parameter)
{
    Execute(() => GetProvider(parameter).DoSomething());
}

But I need some function that return values. What are the best ways to do it? I have found two now:

1) Create a copy of Execute method with Func

private T Execute<T>(Func<T> action)
{
   Logger.Start();
   try
   {
      return action();
   }
   catch(Exception exception)
   {
      Logger.WriteException();
      throw;
   }
   finally
   {
       Logger.Finish();
   }
}

This method works but has some copy paste as well.

2) Trick the parameter into being an Action:

public Result DoSomething(string parameter)
{
    Result result = null;
    Execute(() => result = GetProvider(parameter).DoSomething());
    return result;
}

This does not require copy paste but does not look so nice.

Is there a way to join Action and Func somehow to avoid any of these methods or may be there is another way to achieve the same result?


Solution

  • A third option is to still overload Execute, but make the Action version work in terms of the Func version:

    private void Execute(Action action)
    {
        // We just ignore the return value here
        Execute(() => { 
            action();
            return 0; 
        });
    }
    

    Of course all this would be simpler if void were more like a "real" type (like Unit in F# et al), at which point we could just have Task<T> instead of Task and Task<T> as well...