CSharp/C# Tutorial - C# Generic Delegate

A delegate type may contain generic type parameters. For example:

public delegate T Converter<T> (T arg);

With this definition, we can write a generalized method that works on any type:

public class Util {
    public static void Process<T> (T[] values, Converter<T> t) {
       for (int i = 0; i < values.Length; i++)
           values[i] = t (values[i]);

class Main {
    static void Main() {
       int[] values = { 1, 2, 3 };
       Util.Process (values, Square); // Hook in Square
       foreach (int i in values){
           Console.Write (i + " "); // 1 4 9
    static int Square (int x) { 
       return x * x; 

Func and Action Delegates

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

These delegates are the Func and Action delegates, defined in the System namespace:

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 can cover almost all methods.


The following code shows how to use a Func delegate that takes a single argument of type T and returns a same-typed value:

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

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

Delegate types are all incompatible with each other, even if their signatures are the same.

Multicast delegates are considered equal if they reference the same methods in the same order.