Learn Action and Func Delegates in C#

Introduction

In C#, delegates are powerful tools that enable methods to be passed as parameters. Two of the most commonly used delegate types are Action and Func. These generic delegates simplify the use of delegates by providing built-in types for common scenarios. This article explores Action and Func delegates, their differences, and practical examples of how to use them effectively.

Action Delegates

An Action delegate represents a method that performs an action but does not return a value. It can take zero or more parameters.

Syntax

public delegate void Action();
public delegate void Action<T>(T arg);
public delegate void Action<T1, T2>(T1 arg1, T2 arg2);
// and so on up to 16 parameters

Example

using System;
public class ActionExample
{
    public static void PrintMessage()
    {
        Console.WriteLine("Hello, World!");
    }

    public static void PrintNumber(int number)
    {
        Console.WriteLine($"Number: {number}");
    }
    public static void Main()
    {
        Action action = PrintMessage;
        action();
        Action<int> actionWithParam = PrintNumber;
        actionWithParam(42);
    }
}

In this example, PrintMessage and PrintNumber are methods that match the Action delegate signatures. The Action delegate encapsulates these methods and allows them to be called through the delegate instance.

Func Delegates

A Func delegate is used to represent a method that returns a value. It can take zero or more parameters, but it must return a value.

Syntax

public delegate TResult Func<TResult>();
public delegate TResult Func<T, TResult>(T arg);
public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
// and so on up to 16 parameters

Example

using System;
public class FuncExample
{
    public static int GetNumber()
    {
        return 42;
    }
    public static string ConcatenateStrings(string str1, string str2)
    {
        return str1 + str2;
    }
    public static void Main()
    {
        Func<int> func = GetNumber;
        int result = func();
        Console.WriteLine($"Result: {result}");
        Func<string, string, string> funcWithParams = ConcatenateStrings;
        string concatenated = funcWithParams("Hello, ", "World!");
        Console.WriteLine($"Concatenated: {concatenated}");
    }
}

In this example, GetNumber and ConcatenateStrings are methods that match the Func delegate signatures. The Func delegate encapsulates these methods and allows them to be called through the delegate instance.

Differences Between Action and Func

The main difference between Action and Func delegates is their return types.

  • Action: Represents methods that do not return a value (void).
  • Func: Represents methods that return a value.

Practical Usage

Delegates, including Action and Func, are commonly used in event handling, callback methods, and as parameters for methods that perform operations on collections.

Example. Using Action and Func in a List Operation.

using System;
using System.Collections.Generic;
public class ListOperationExample
{
    public static void PerformActionOnList<T>(List<T> list, Action<T> action)
    {
        foreach (var item in list)
        {
            action(item);
        }
    }
    public static List<TResult> TransformList<T, TResult>(List<T> list, Func<T, TResult> func)
    {
        var resultList = new List<TResult>();
        foreach (var item in list)
        {
            resultList.Add(func(item));
        }
        return resultList;
    }
    public static void Main()
    {
        var numbers = new List<int> { 1, 2, 3, 4, 5 };
        PerformActionOnList(numbers, n => Console.WriteLine($"Number: {n}"));
        var doubledNumbers = TransformList(numbers, n => n * 2);
        PerformActionOnList(doubledNumbers, n => Console.WriteLine($"Doubled Number: {n}"));
    }
}

In this example, PerformActionOnList takes an Action<T> to operate on each item in the list, while TransformList takes a Func<T, TResult> to transform each item in the list and return a new list.

Conclusion

Action and Func delegates are essential tools in C# that allow for more flexible and reusable code by enabling methods to be passed as parameters. Understanding their differences and how to use them can greatly enhance your ability to write clean and efficient C# programs. By leveraging these delegates, you can create more abstract and higher-level methods that operate on a wide range of data types and operations.


Similar Articles