C# Action

Action is one of the pre-built delegates in C# to store a method reference. The action delegate only accepts those methods that have a void return type. The action delegate has 16 overload methods that allow you to store a method reference that can accept up to 16 parameters. In this post, we will learn about the C# action delegate, both generic and non-generic, with examples.


A delegate in C# represents a reference type that encapsulates a method. When we declare a delegate type, we specify some parameters and a return type along with the delegate name. We can only store those methods in delegates that have the same parameters and the same return type. C# introduced some pre-built delegates so that we don’t have to declare delegates every time. Below are the pre-built delegates in C#.

  1. Action
  2. Predicate
  3. Func

Action delegate method references can take up to 16 parameters and always have a void return type. In a predicate delegate, we can give only one parameter and return one boolean value. In the Func delegate, we can store one return value and take up to 16 parameters.

An action delegate is used to store a function that performs action on the associated object, while a C# predicate is used to check some condition on the object. The Func delegate is used in both scenarios.

Action Delegate Types

There are two variants of the C# action delegate.

  1. Action: Non-generic action delegate
  2. Action<T>: Generic action delegate

Non-Generic Action Delegate

A non-generic C# action delegate can store a function reference that has no parameters and a void return type.

Below is an example.

public static void DoWork()
    Console.WriteLine("Hi, I am doing work.");

static void Main(string[] args)
    Action doWorkAction = new Action(DoWork);
    doWorkAction(); //Print "Hi, I am doing work."

In the above example, I have declared a DoWork() method that has a void return type and does not take any parameters. Under the Main method, I have declared an action delegate and assigned the DoWork() method to the constructor of the action delegate.

In the next line, I have called the action delegate, which prints the console message specified in the DoWork() method.

The biggest drawback of the above non-generic action delegate is that we cannot define any parameters in the reference method.

To resolve this problem, generic delegates are introduced.

Generic Action Delegate

In a generic action delegate, we can specify the data type for the parameters. So an action delegate is a type-safe way to store method references.

The generic action delegate has 16 overload methods to take up to 16 parameters.

We have to choose the action delegate according to the method we want to store. If our method takes two parameters, then we have to choose the action delegate, which has two parameters: Action<in T1, T2>(T1 arg1, T2 arg2). Below are some examples.

static void Main(string[] args)
    Action<int> firstAction = DoWorkWithOneParameter;
    Action<int, int> secondAction = DoWorkWithTwoParameters;
    Action<int, int, int> thirdAction = DoWorkWithThreeParameters;

    firstAction(1); // Print 1
    secondAction(1, 2); // Print 1-2
    thirdAction(1, 2, 3); //Print 1-2-3

public static void DoWorkWithOneParameter(int arg)

public static void DoWorkWithTwoParameters(int arg1, int arg2)
    Console.WriteLine(arg1 + "-" + arg2);

public static void DoWorkWithThreeParameters(int arg1, int arg2, int arg3)
    Console.WriteLine(arg1 + "-" + arg2 + "-" + arg3);

In the above example, we have three methods. The first method takes one parameter, the second method takes two parameters, and the third method takes three parameters.

In the main method, we declare three action delegates. In the first action delegate, we specify the int data type as a generic parameter, which means it can accept only those methods that take only the int data type as a parameter.

In the second and third action delegate, we specify two and three generic parameters to specify that this delegate can take only those methods that accept two and three parameters, respectively.

C# Action delegate with Anonymous method

We can also use an anonymous method with the action delegate in C#. In an anonymous method, we define an inline method without specifying its name. It is an easy way to define the delegate method. Below is an example.

using System;
using System.Collections.Generic;
using System.Linq;
public class Program
	public static void Main()
		Action<string> act = new Action<string>(delegate(string message) {
		act("this is my message");

Action with Lambda Expression

We can use a lambda expression with an action delegate. Below is an example.

static void Main(string[] args)
    Action act = () =>
        Console.WriteLine("No Parameter");

    Action<int> actWithOneParameter = (arg1) =>
            Console.WriteLine("Par: " + arg1);

    Action<int, int> actWithTwoParameter = (arg1, arg2) =>
            Console.WriteLine("Par1: " + arg1 + ", Par2: " + arg2);

    actWithTwoParameter(1, 2);


C# provides an action delegate type to store method references, which have no return type and can take up to 16 parameters. C# action delegate can be used with anonymous function and lambda expressions.