C# позволяет передавать методы в качестве параметров функциям, значительно повышая гибкость и повторное использование кода. Эта возможность имеет решающее значение для реализации обратных вызовов, обработчиков событий и стратегических шаблонов, где поведение во время выполнения определяет конкретное действие. В этой статье рассматриваются различные подходы к достижению этого, с упором на пользовательские делегаты, Func<>
и Action<>
.
Оглавление
- Использование пользовательских делегатов для передачи методов в качестве параметров
- Использование делегата
Func<>
- Использование делегата
Action<>
- Заключение
Использование пользовательских делегатов для передачи методов в качестве параметров
Делегаты в C# служат указателями на функции с проверкой типов. Создание пользовательского делегата обеспечивает точный контроль и ясность, когда сигнатура метода отличается от встроенных делегатов Func<>
или Action<>
. Рассмотрим функцию, выполняющую операцию над числом и затем отображающую результат, где сама операция является параметром.
// Определение пользовательского делегата
public delegate double MathOperation(double x);
public class Example
{
public static void PerformOperationAndPrint(double num, MathOperation operation)
{
double result = operation(num);
Console.WriteLine($"Result: {result}");
}
public static double Square(double x) => x * x;
public static double Cube(double x) => x * x * x;
public static void Main(string[] args)
{
PerformOperationAndPrint(5, Square); // Output: Result: 25
PerformOperationAndPrint(5, Cube); // Output: Result: 125
}
}
MathOperation
выступает в роли делегата, представляющего метод, принимающий double
и возвращающий double
. PerformOperationAndPrint
принимает этот делегат, позволяя использовать Square
, Cube
или любой соответствующий метод.
Использование делегата Func<>
Func<>
— это универсальный делегат, представляющий метод с нулем или более входными параметрами и возвращаемым значением. Его встроенный характер упрощает многие сценарии. Давайте переработаем предыдущий пример:
public class Example
{
public static void PerformOperationAndPrint(double num, Func<double, double> operation)
{
double result = operation(num);
Console.WriteLine($"Result: {result}");
}
public static double Square(double x) => x * x;
public static double Cube(double x) => x * x * x;
public static void Main(string[] args)
{
PerformOperationAndPrint(5, Square); // Output: Result: 25
PerformOperationAndPrint(5, Cube); // Output: Result: 125
}
}
Это достигает того же результата с меньшим количеством кода. Func<double, double>
указывает метод, принимающий double
и возвращающий double
. Универсальные параметры типа адаптируются к различным сигнатурам методов (например, Func<int, string>
).
Использование делегата Action<>
Action<>
— это универсальный делегат для методов с нулем или более входными параметрами и типом возвращаемого значения void
(без возвращаемого значения). Используйте его, когда методы не возвращают значения.
public class Example
{
public static void PerformAction(string message, Action<string> action)
{
action(message);
}
public static void PrintMessage(string msg) => Console.WriteLine(msg);
public static void PrintMessageToUpper(string msg) => Console.WriteLine(msg.ToUpper());
public static void Main(string[] args)
{
PerformAction("Hello, world!", PrintMessage); // Output: Hello, world!
PerformAction("Hello, world!", PrintMessageToUpper); // Output: HELLO, WORLD!
}
}
Action<string>
представляет метод, принимающий строку и ничего не возвращающий. PerformAction
использует это для выполнения различных действий печати.
Заключение
Передача методов в качестве параметров — мощная функция C#. Пользовательские делегаты обеспечивают максимальный контроль, в то время как Func<>
и Action<>
предоставляют удобные встроенные решения. Лучший подход зависит от конкретных требований вашего приложения. Освоение этих методов является ключом к написанию более адаптируемого и поддерживаемого кода C#.