Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Encapsulating Action<T> and Func<T>?

I'm trying to make a design for some sort of IExecutable interface. I will not get into details, but the point is that I have several Actions that need to be executed from a base class. They may take different parameters (no big deal), and they may/may not return a value.

So far, this is my design:

public abstract class ActionBase
{
    // ... snip ...
}

public abstract class ActionWithResultBase<T>: ActionBase
{
    public abstract T Execute();
}

public abstract class ActionWithoutResultBase: ActionBase
{
    public abstract void Execute();
}

So far, each of my concrete actions need to be a child from either ActionWithResultBase or ActionWithoutResult base, but I really don't like that. If I could move the definition of Execute to ActionBase, considering that the concrete class may or may not return a value, I will have achieved my goal.

Someone told me this could be done with using Func and Action, for which I totally agree, but I can't find a way to have that into one single class so that the caller would know if the action is going to return a value or not.

Brief: I want to do something like:

// Action1.Execute() returns something.
var a = new Action1();
var result = a.Execute();

// Action2.Execute() returns nothing.
var b = new Action2();
b.Execute();
like image 354
Alpha Avatar asked Nov 25 '10 16:11

Alpha


People also ask

What is the difference between action t and FUNC T >?

Actions can only take input parameters, while Funcs can take input and output parameters. It is the biggest difference between them. An action can not return a value, while a func should return a value in the other words.

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 are func and action?

Func is a delegate that points to a method that accepts one or more arguments and returns a value. Action is a delegate that points to a method which in turn accepts one or more arguments but returns no value. In other words, you should use Action when your delegate points to a method that returns void.

What is action t used for in an application?

Action<T> Delegate (System)Encapsulates a method that has a single parameter and does not return a value.


1 Answers

If you want a lightweight solution, then the easiest option would be to write two concrete classes. One will contain a property of type Action and the other a property of type Func<T>:

public class ActionWithResult<T> : ActionBase { 
  public Func<T> Action { get; set; } 
}

public class ActionWithoutResult : ActionBase {
  public Action Action { get; set; }
}

Then you can construct the two types like this:

var a1 = new ActionWithResult<int> { 
  CanExecute = true,
  Action = () => { 
    Console.WriteLine("hello!");
    return 10; 
  }
}

If you don't want to make Action property read/write, then you could pass the action delegate as an argument to the constructor and make the property readonly.

The fact that C# needs two different delegates to represent functions and actions is quite annoying. One workaround that people use is to define a type Unit that represents "no return value" and use it instead of void. Then your type would be just Func<T> and you could use Func<Unit> instead of Action. The Unit type could look like this:

public class Unit {
  public static Unit Value { get { return null; } }
}

To create a Func<Unit> value, you'll write:

Func<Unit> f = () => { /* ... */ return Unit.Value; }
like image 151
Tomas Petricek Avatar answered Sep 27 '22 22:09

Tomas Petricek