Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 923
Ilya Chernomordik Avatar asked Apr 02 '13 13:04

Ilya Chernomordik


People also ask

What is the difference between Func and Action delegate?

An Action type delegate is the same as Func delegate except that the Action delegate doesn't return a value. In other words, an Action delegate can be used with a method that has a void return type. It can contain minimum 1 and maximum of 16 input parameters and does not contain any output parameter.

What is the use of func action and predicate in C#?

Action takes zero, one or more input parameters, but does not return anything. Predicate is a special kind of Func. It represents a method that contains a set of criteria mostly defined inside an if condition and checks whether the passed parameter meets those criteria or not.

What are func and predicate delegates?

Func is a delegate that returns a value. Action is a delegate that returns void. A Predicate is similar to a Func that returns true or false. A delegate is like a method variable. The delegate can be assigned to any method where the parameters and return types match.

Could you explain the difference between func vs Action vs predicate?

Func<T> and its equivalent delegate types are used for methods that return values (functions). T represents the return value. Action and its equivalent delegate types are used for methods that have no return value (procedures). Predicate is just an alternative form of Func<bool> that returns a boolean.


2 Answers

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

like image 67
Jon Skeet Avatar answered Nov 06 '22 12:11

Jon Skeet


Create a copy of Execute that converts the Func into an Action. You only have to write that ugly code once, and you don't end up with a complete second copy of the Execute method:

private T Execute<T>(Func<T> func)
{
    T result = default(T);
    this.Execute(() => { result = func(); });
    return result;
}

...

public Result DoSomething(string parameter)
{
    return Execute(() => GetProvider(parameter).DoSomething());
}
like image 39
p.s.w.g Avatar answered Nov 06 '22 12:11

p.s.w.g