This is a C# function object. Action objects return no values. The Action type is similar to a void
method—this generic type is found in the System
namespace.
To specify an Action, we must have no return value. The Action must never return a value onto the evaluation stack. Often we use lambdas to specify Actions.
These Actions point to anonymous functions. These functions cannot return values. An Action instance can receive parameters, but cannot return values.
int
argument when invoked. It returns no result—it is a void
delegate method.using System; // Version 1: this Action uses one parameter. Action<int> example1 = (int x) => Console.WriteLine("Write {0}", x); example1.Invoke(1); // Version 2: second example uses 2 parameters. Action<int, int> example2 = (x, y) => Console.WriteLine("Write {0} and {1}", x, y); example2.Invoke(2, 3); // Version 3: third example uses no parameter. Action example3 = () => Console.WriteLine("Done"); example3.Invoke();Write 1 Write 2 and 3 Done
How much slower are delegate method calls than direct method calls? To test this, we use the Action type with a single parameter.
Method1
(which uses no Action) is called directly 100 million times.Method1
is invoked the same number of times.using System; using System.Diagnostics; class Program { const int _max = 100000000; static void Main() { // Create Action delegate for Method1. Action<int> action = new Action<int>(Method1); var s1 = Stopwatch.StartNew(); // Version 1: use direct call. for (int i = 0; i < _max; i++) { Method1(5); } s1.Stop(); var s2 = Stopwatch.StartNew(); // Version 2: use Action (delegate) call. for (int i = 0; i < _max; i++) { action.Invoke(5); } s2.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000 * 1000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000 * 1000) / _max).ToString("0.00 ns")); } static void Method1(int param) { // Dummy. if (param == -1) { throw new Exception(); } } }0.32 ns Direct call 3.52 ns Action Invoke call
abstract
Next we benchmark abstract
methods. An Action int
can be an instance that points to any function that receives an int
parameter.
abstract
class
. We repeatedly call a method on it.abstract
class
reference.using System; using System.Diagnostics; abstract class A { public abstract void MethodA(int y); } class AB : A { public override void MethodA(int y) { } } class Program { static void MethodA(int y) { } static void Main() { A abst = new AB(); abst.MethodA(0); Action<int> action = new Action<int>(MethodA); action.Invoke(0); const int max = 100000000; var s1 = Stopwatch.StartNew(); // Version 1: use abstract class method. for (int i = 0; i < max; i++) { abst.MethodA(i); abst.MethodA(i); } s1.Stop(); var s2 = Stopwatch.StartNew(); // Version 2: use Action. for (int i = 0; i < max; i++) { action.Invoke(i); action.Invoke(i); } s2.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / max).ToString("0.00 ns")); } }3.54 ns Abstract call 6.68 ns Action Invoke() call
Dictionary
It is possible to use Action as the value in a Dictionary
instance. This makes it possible to call functions by a string
key.
static
void
methods based on simple string
keys.Dictionary
of an abstract
class
. Then, instantiate each method as an instance of a derived class
.using System; using System.Collections.Generic; class Program { static void Main() { Dictionary<string, Action> dict = new Dictionary<string, Action>(); dict["cat"] = new Action(Cat); dict["dog"] = new Action(Dog); dict["cat"].Invoke(); dict["dog"].Invoke(); } static void Cat() { Console.WriteLine("CAT"); } static void Dog() { Console.WriteLine("DOG"); } }CAT DOG
The Invoke method receives a number of arguments equal to the specific type of Action. We must specify these arguments in the Action type declaration.
What is the difference between Action and Func
? The Action type receives parameters but does not return a parameter. Func
receives parameters and returns a result value.
Func
always returns something.Programs use Actions for many purposes. The Action type specifies a function object that can receive parameters, but never returns a value onto the stack.