In C#, delegates like Action and Func allow you to treat behavior as data — meaning you can pass methods around like variables.
This concept is powerful and opens doors to cleaner, more flexible, and decoupled code.
In this article, we’ll explore:
- What Action and Func are
- How to use them effectively
- Real-world examples using design patterns like Strategy and Command
What Are Action and Func in C#?
Action Delegate
Represents a method that returns void.
Can take 0 to 16 input parameters.
Action<string> greet = name => Console.WriteLine($"Hello, {name}!");
greet("Alice"); // Output: Hello, Alice!
Func Delegate
Represents a method that returns a value.
Can take 0 to 16 input parameters, last type is the return type.
Func<int, int, int> add = (a, b) => a + b;
int sum = add(3, 4); // sum = 7
Why Use Action and Func?
Decouple logic from implementation.
Useful in LINQ, event handling, callbacks, dynamic method binding.
Helps implement design patterns with less boilerplate.
Real-World Example 1: Strategy Pattern Using Func
The Strategy Pattern allows you to swap algorithms dynamically.
Let’s build a tax calculator that can apply different tax strategies using Func.
Real-World Example 1: Strategy Pattern Using Func
The Strategy Pattern allows you to swap algorithms dynamically.
Let’s build a tax calculator that can apply different tax strategies using Func.
public class TaxCalculator
{
private readonly Func<decimal, decimal> _taxStrategy;
public TaxCalculator(Func<decimal, decimal> taxStrategy)
{
_taxStrategy = taxStrategy;
}
public decimal Calculate(decimal amount) => _taxStrategy(amount);
}
Usage
var standardTax = new TaxCalculator(amount => amount * 0.2m);
Console.WriteLine(standardTax.Calculate(100)); // Output: 20
var reducedTax = new TaxCalculator(amount => amount * 0.1m);
Console.WriteLine(reducedTax.Calculate(100)); // Output: 10`
Why It's Clean
No need for multiple strategy classes.
Easily inject behavior via Func.
Real-World Example 2: Command Pattern Using Action
The Command Pattern encapsulates a request as an object.
Let’s create a simple remote control that executes commands using Action.
public class RemoteControl
{
private readonly Action _command;
public RemoteControl(Action command)
{
_command = command;
}
public void PressButton() => _command();
}
Usage
var turnOnLight = new RemoteControl(() => Console.WriteLine("Light On"));
turnOnLight.PressButton(); // Output: Light On
var playMusic = new RemoteControl(() => Console.WriteLine("Music Playing"));
playMusic.PressButton(); // Output: Music Playing
Advantage
You can queue commands, undo, or log them — all using Action.
Combining Action and Func: Workflow Example
Let’s simulate a data processing pipeline:
Func<string> fetchData = () => "raw data";
Func<string, string> processData = data => data.ToUpper();
Action<string> saveData = result => Console.WriteLine($"Saved: {result}");
var raw = fetchData();
var processed = processData(raw);
saveData(processed); // Output: Saved: RAW DATA
*Final Thoughts : *
Understanding and leveraging Action and Func can simplify your code, especially when implementing common patterns. They enable dynamic, reusable behaviors that are perfect for modern C# development.
Next time you’re about to create multiple strategy or command classes, consider whether delegates can do the job with less overhead.
References
Top comments (2)
hey, thanks for sharing, you can also use CSharp syntax highlighting this way:
Great, thanks! Unfortunately, I'm not very good at formatting.
I’ll keep it in mind for next time.