Introduction
In this article, we are going to discuss Action and Func delegates in C# and
how we use them. As we already know, a Delegate in C# is a type-safe method
pointer and we are using it to handle the callback or an event. Actions and
Funcs are just delegates but are pre-defined in System Namespace so that we
don’t need to define the custom delegates manually.
Syntax
Both Action and Func delegates can have multiple input parameters. A Func
delegate returns a value while an Action does not, this is the only difference
between them.
C# provides 17 overloads of Action delegate in the System Namespace, one of
them is:
public delegate void Action<in T>(T obj);
This Action delegate would only accept one argument of type T. However,
it can support up to 16 arguments of type T.
Similarly, there are total of 17 overloads of Func delegate defined in
the System Namespace, one of them is:
public delegate TResult Func<out TResult>();
This Func delegate doesn't take any input but returns the result of the type
TResult. However, it can support up to 16 arguments of type T.
Code Examples
Let’s write a small C# console program so that we understand how to use the
Action and Func delegates and what are various ways or expressions to assign
a method reference to those.
Let’s start with Action delegate first:
static void PrintAWord(string name)
{
Console.WriteLine(name);
}
static void Main(string[] args)
{
List<string> words = new List<string> { "apple", "banana", "cherry", "date" };
Action<string> actionPrintWord = PrintAWord;
words.ForEach(w=> actionPrintWord(w));
}
In this example, we are going to print all the string fromList collection so
let's create a list of strings first and then an Action<string>
delegate that accepts the one string parameter. Now let's use the
List<String>.ForEach method with an Action<string> delegate as
an argument to print out each string in the list.
We can shorten this example by using the anonymous method:
static void Main(string[] args)
{
List<string> words = new List<string> { "apple", "banana", "cherry", "date" };
words.ForEach(delegate(string word){
Console.WriteLine(word);
});
}
Furthermore, we can make this example more readable by using the lambda
expression which we also call the arrow expression:
static void Main(string[] args)
{
List<string> words = new List<string> { "apple", "banana", "cherry", "date" };
words.ForEach(w=> Console.WriteLine(w));
}
With this, we conclude the various ways to create the Action delegate.
Now let’s see the Func delegate example:
static int Square(int n)
{
return n * n;
}
static void Main(string[] args)
{
Func<int, int> funcSquare = Square;
Console.WriteLine(funcSquare(5));
}
In this example, we define a Func<int, int> delegate - funcSquare that
refers to the method int square(int) which represents a mathematical
function that squares a number. Now let's print the square of 5 in the
console by calling the funcSquare(5) in the Console.WriteLine() method.
We can shorten this example by using the anonymous method:
static void Main(string[] args)
{
Func<int, int> funcSquare = delegate(int n) { return n * n; };
Console.WriteLine(funcSquare(5));
}
Furthermore, we can make this example more readable by using the lambda/arrow
expression:
static void Main(string[] args)
{
Func<int, int> funcSquare = n => n * n;
Console.WriteLine(funcSquare(5));
}
With this, we conclude the various ways to create the Func delegate.
Conclusion
In this article, we have learned that Action and Func delegates are easy and
quick to define delegates, thus helping us to keep the code shorter and more
manageable. We should use generic Action<T> delegate to refer to a
method that has zero or more parameters and returns void, and use generic
Func<T,TResult> delegate to refer to a method that has zero or more
parameters and returns a value.
Comments