C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
So: An Action instance is similar to a void method. The program shows how to Invoke the Action instances.
Action 1: This Action receives one int argument when invoked. It returns no result—it is a void delegate method.
Int, uintAction 2: This Action receives 2 arguments, named "x" and "y." It prints them out to the console.
Action 3: This Action receives no parameters. So we have a method that receives no arguments, and returns no values.
C# program that uses Action type and Invoke
using System;
class Program
{
static void Main()
{
// Example Action instances.
// ... First example uses one parameter.
// ... Second example uses two parameters.
// ... Third example uses no parameter.
// ... None have results.
Action<int> example1 =
(int x) => Console.WriteLine("Write {0}", x);
Action<int, int> example2 =
(x, y) => Console.WriteLine("Write {0} and {1}", x, y);
Action example3 =
() => Console.WriteLine("Done");
// Call the anonymous methods.
example1.Invoke(1);
example2.Invoke(2, 3);
example3.Invoke();
}
}
Output
Write 1
Write 2 and 3
Done
Overview: This program introduces the Method1 method, which contains some dummy code for testing.
Version 1: In the first loop, Method1 (which uses no Action) is called directly 100 million times.
Version 2: In the second loop, an Action instance that points to Method1 is invoked the same number of times.
Result: For a method with 1 parameter and no return value, the Action invocation costs more than 3 ns extra each time.
C# program that tests Action invocation
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"));
Console.Read();
}
static void Method1(int param)
{
// Dummy.
if (param == -1)
{
throw new Exception();
}
}
}
Output
0.32 ns Direct call
3.52 ns Action Invoke call
Version 1: In this version of the code, we test an abstract class. We repeatedly call a method on it.
AbstractBenchmarkVersion 2: Here we call a method on an Action instance. The code performs the same number of method calls as version 1.
Result: The Action was slower to call than the method from the abstract class reference.
C# program that benchmarks abstract
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"));
Console.Read();
}
}
Output
3.54 ns Abstract call
6.68 ns Action Invoke() call
Here: In this example, we invoke two static void methods based on simple string keys.
StaticIdea: You could use a Dictionary of an abstract class. Then, instantiate each method as an instance of a derived class.
InheritanceC# program that uses Dictionary with Action
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");
}
}
Output
CAT
DOG
Tip: This information is determined at compile-time, before runtime. If a program compiles, it uses the correct argument types.
So: An Action instance never returns anything, while the Func always returns something.
FuncNote: Thanks to Turker Tunali for helping clarify the Action descriptive text. All contributions are appreciated.