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?
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.
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.
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.
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.
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...
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());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With