CSharp - Func and Action Delegates

Introduction

With generic delegates, we can create a small set of delegate types to represent methods of any return type and any reasonable number of arguments.

For example, the following delegate can represent any method with one parameter and return declaration.

public delegate R MyDelegate<T> (T arg);

C# defines Func and Action delegates in the System namespace to represent all possible methods.

delegate TResult Func <out TResult>                ();
delegate TResult Func <in T, out TResult>          (T arg);
delegate TResult Func <in T1, in T2, out TResult>  (T1 arg1, T2 arg2);
 ... and so on, up to T16

delegate void Action                 ();
delegate void Action <in T>          (T arg);
delegate void Action <in T1, in T2>  (T1 arg1, T2 arg2);
 ... and so on, up to T16

These delegates are extremely general.

The only practical scenarios not covered by these delegates are ref/out and pointer parameters.

Suppose we have the following code.

Demo

using System;
delegate T ConverterFunction<T>(T arg);
class Util//  w  ww. j ava2  s.  c  om
{
    public static void Convert<T>(T[] values, ConverterFunction<T> t)
    {
        for (int i = 0; i < values.Length; i++)
            values[i] = t(values[i]);
    }
}

class Test
{
    static void Main()
    {
        int[] values = { 1, 2, 3 };
        Util.Convert(values, Square);
        foreach (int i in values)
            Console.Write(i + "  ");
    }
    static int Square(int x) => x * x;
}

Result

By using the Func delegate, we can rewrite the code as

Demo

using System;

class Util/*from w  w w  . j  a  va2  s  .co m*/
{
    public static void Convert<T>(T[] values, Func<T,T> t)
    {
        for (int i = 0; i < values.Length; i++)
            values[i] = t(values[i]);
    }

}

class Test
{
    static int Square(int x) => x * x;
    static void Main()
    {
        int[] values = { 1, 2, 3 };
        Util.Convert(values, Test.Square);
        foreach (int i in values)
            Console.Write(i + "  ");
    }

}

Result

ConverterFunction delegate is replaced by a Func delegate that takes a single argument of type T and returns a same-typed value:

static void Transform<T> (T[] values, Func<T,T> transformer)
{
       for (int i = 0; i < values.Length; i++)
         values[i] = transformer (values[i]);
}

Related Topics