What are generic delegates in C#?

Generic delegates in C# allow you to create delegate types with type parameters, providing flexibility to work with different data types without defining separate delegate declarations for each type. The .NET Framework provides several built-in generic delegates in the System namespace that eliminate the need for custom delegate definitions in most scenarios.

Syntax

Following is the syntax for declaring a custom generic delegate −

delegate TResult DelegateName<T, TResult>(T parameter);

Built-in generic delegates use these syntaxes −

Action<T> actionDelegate = method;     // void return type
Func<T, TResult> funcDelegate = method; // with return type

Built-in Generic Delegates

The .NET Framework provides three main built-in generic delegates −

Delegate Type Purpose Return Type
Action<T> Points to methods that take parameters but return void void
Func<T, TResult> Points to methods that take parameters and return a value TResult
Predicate<T> Points to methods that take one parameter and return bool bool

Using Built-in Generic Delegates

Example with Action and Func

using System;

class MathOperations {
    public static void PrintSquare(int number) {
        Console.WriteLine("Square of " + number + " is: " + (number * number));
    }
    
    public static int AddNumbers(int a, int b) {
        return a + b;
    }
    
    public static bool IsEven(int number) {
        return number % 2 == 0;
    }
    
    static void Main(string[] args) {
        // Action delegate - points to method with void return
        Action<int> printAction = PrintSquare;
        printAction(5);
        
        // Func delegate - points to method with return value
        Func<int, int, int> addFunc = AddNumbers;
        int result = addFunc(10, 20);
        Console.WriteLine("Addition result: " + result);
        
        // Predicate delegate - points to method returning bool
        Predicate<int> evenPredicate = IsEven;
        Console.WriteLine("Is 8 even? " + evenPredicate(8));
        Console.WriteLine("Is 7 even? " + evenPredicate(7));
    }
}

The output of the above code is −

Square of 5 is: 25
Addition result: 30
Is 8 even? True
Is 7 even? False

Custom Generic Delegate

Example

using System;

delegate T MathOperation<T>(T x, T y);

class Calculator {
    public static int Add(int a, int b) {
        return a + b;
    }
    
    public static double Multiply(double x, double y) {
        return x * y;
    }
    
    public static string Concatenate(string s1, string s2) {
        return s1 + s2;
    }
    
    static void Main(string[] args) {
        // Generic delegate with int type
        MathOperation<int> intOp = Add;
        Console.WriteLine("Integer addition: " + intOp(15, 25));
        
        // Generic delegate with double type
        MathOperation<double> doubleOp = Multiply;
        Console.WriteLine("Double multiplication: " + doubleOp(3.5, 2.0));
        
        // Generic delegate with string type
        MathOperation<string> stringOp = Concatenate;
        Console.WriteLine("String concatenation: " + stringOp("Hello ", "World"));
    }
}

The output of the above code is −

Integer addition: 40
Double multiplication: 7
String concatenation: Hello World

Using Generic Delegates with Lambda Expressions

Example

using System;

class LambdaExample {
    static void Main(string[] args) {
        // Action with lambda expression
        Action<string> greet = name => Console.WriteLine("Hello, " + name + "!");
        greet("Alice");
        
        // Func with lambda expression
        Func<int, int, int> multiply = (x, y) => x * y;
        Console.WriteLine("Multiplication: " + multiply(6, 7));
        
        // Predicate with lambda expression
        Predicate<int> isPositive = num => num > 0;
        Console.WriteLine("Is -5 positive? " + isPositive(-5));
        Console.WriteLine("Is 10 positive? " + isPositive(10));
    }
}

The output of the above code is −

Hello, Alice!
Multiplication: 42
Is -5 positive? False
Is 10 positive? True

Conclusion

Generic delegates in C# provide type safety and reusability by allowing the same delegate type to work with different data types. The built-in Action<T>, Func<T, TResult>, and Predicate<T> delegates cover most scenarios, eliminating the need for custom delegate declarations in typical applications.

Updated on: 2026-03-17T07:04:35+05:30

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements