C# > Advanced C# > Delegates and Events > Built-in Delegates (Func, Action, Predicate)
Using Built-in Delegates (Func, Action, Predicate) for Flexible Operations
This code demonstrates how to leverage the built-in delegates Func
, Action
, and Predicate
in C# to create highly flexible and reusable code. These delegates eliminate the need to define custom delegate types in many common scenarios, leading to cleaner and more concise code.
Understanding Func, Action, and Predicate
Func
, Action
, and Predicate
are pre-defined delegate types in C#. They provide a convenient way to represent methods without explicitly declaring a new delegate type. This reduces boilerplate code and improves readability.Func
: Represents a method that takes zero or more input parameters and returns a value. The last type parameter is always the return type (e.g., Func
represents a method that takes an integer and returns a string).Action
: Represents a method that takes zero or more input parameters and returns no value (void
). (e.g., Action
represents a method that takes a string and returns void).Predicate
: Represents a method that takes one input parameter and returns a boolean value (bool
). It is typically used for filtering or testing conditions (e.g., Predicate
represents a method that takes an integer and returns true or false).
Code Example Demonstrating Func
This example demonstrates the use of Func
to represent a method that calculates the square of an integer. It then shows how to use this Func
delegate directly and also within the Select
LINQ method to transform a list of integers.
using System;
using System.Collections.Generic;
public class FuncExample
{
public static void Main(string[] args)
{
// Func: Takes an integer and returns its square
Func<int, int> square = x => x * x;
// Use the Func delegate
int result = square(5);
Console.WriteLine($"The square of 5 is: {result}"); // Output: The square of 5 is: 25
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
// Use Func in LINQ's Select method
var squaredNumbers = numbers.Select(square);
Console.WriteLine($"Squared Numbers: {string.Join(", ", squaredNumbers)}"); // Output: Squared Numbers: 1, 4, 9, 16, 25
}
}
Code Example Demonstrating Action
This example demonstrates the use of Action
to represent a method that prints a string to the console. The Action
delegate does not return any value. It also demonstrates an Action with multiple input parameters Action
.
using System;
public class ActionExample
{
public static void Main(string[] args)
{
// Action: Takes a string and prints it to the console
Action<string> printMessage = message => Console.WriteLine(message);
// Use the Action delegate
printMessage("Hello, Action delegate!"); // Output: Hello, Action delegate!
// Action with multiple parameters.
Action<string, int> printNameAge = (name, age) => Console.WriteLine($"Name: {name}, Age: {age}");
printNameAge("Alice", 30);
}
}
Code Example Demonstrating Predicate
This example demonstrates the use of Predicate
to represent a method that checks if an integer is even. It shows how to use this Predicate
delegate directly and within the Where
LINQ method to filter a list of integers.
using System;
using System.Collections.Generic;
using System.Linq;
public class PredicateExample
{
public static void Main(string[] args)
{
// Predicate: Takes an integer and returns true if it's even, false otherwise
Predicate<int> isEven = x => x % 2 == 0;
// Use the Predicate delegate
bool result = isEven(4);
Console.WriteLine($"Is 4 even? {result}"); // Output: Is 4 even? True
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
// Use Predicate in LINQ's Where method
var evenNumbers = numbers.Where(number => isEven(number));
Console.WriteLine($"Even Numbers: {string.Join(", ", evenNumbers)}"); // Output: Even Numbers: 2, 4, 6
// or simply var evenNumbers = numbers.Where(isEven);
}
}
Concepts Behind the Snippet
The core concept behind using Func
, Action
, and Predicate
is to treat methods as first-class citizens. This allows you to pass methods as arguments to other methods, store them in variables, and return them from methods. This is a fundamental principle of functional programming and enables powerful abstraction and code reuse.
Real-Life Use Case
Consider a scenario where you have a list of products, and you want to filter them based on different criteria (e.g., price range, availability, category). You can define separate methods for each criterion and then use a Predicate
to pass the appropriate filtering method to a generic filtering function. This avoids creating multiple filtering functions for each criterion.
Best Practices
Func
, Action
, and Predicate
whenever possible to avoid defining custom delegate types for simple method signatures.
Interview Tip
Be prepared to explain the differences between Func
, Action
, and Predicate
, and provide examples of when you would use each one. Also, be able to discuss the advantages of using these built-in delegates over defining custom delegate types.
When to Use Them
Use Func
, Action
, and Predicate
when you need to represent a method that takes zero or more input parameters and returns a value (Func
), returns no value (Action
), or returns a boolean value (Predicate
). They are particularly useful when working with LINQ, event handlers, and other scenarios where you need to pass methods as arguments.
Memory Footprint
The memory footprint of Func
, Action
, and Predicate
is generally small, as they are simply references to methods. However, if you are creating a large number of these delegates, it's important to be aware of the potential for memory overhead. In most common scenarios, the performance impact will be negligible.
Alternatives
The alternative to using Func
, Action
, and Predicate
is to define custom delegate types. While this provides more flexibility, it also adds more boilerplate code. Custom delegates are useful when you need to define specific parameter names or add custom attributes to the delegate type. Another alternative is to use interfaces to define contracts for methods. However, interfaces are better suited for defining the behavior of classes and structs, while delegates are specifically designed for representing methods.
Pros
Cons
FAQ
-
What is the difference between Func and Action?
Func
represents a method that returns a value, whileAction
represents a method that does not return a value (void
). -
When should I use Predicate?
UsePredicate
when you need to represent a method that takes one input parameter and returns a boolean value, typically for filtering or testing conditions. -
Can I use Func and Action with multiple parameters?
Yes, you can useFunc
andAction
with multiple parameters. ForFunc
, the last type parameter specifies the return type. ForAction
, you can specify multiple input parameters. For example:Func
represents a function that takes an int and a string, and returns a boolean.