Функціональне програмування в C#: Action та Func

pic

Action та Func — це ключові делегати в C#, які спрощують функціональне програмування, забезпечуючи готові шаблони для роботи з методами. Вони усувають потребу в створенні власних делегатів, роблячи код чистішим, багаторазово використовуваним та зрозумілим.

Що таке Action та Func?

Делегати в C#: короткий огляд

Делегат — це типізоване посилання на метод, що дозволяє передавати методи як параметри, зберігати їх у змінних або повертати з функцій. Традиційно для цього потрібні власні визначення делегатів, але Action і Func значно спрощують цей процес завдяки готовим шаблонам.

Основні відмінності між Action та Func

  • Action: представляє метод із нульовою або більшою кількістю вхідних параметрів без поверненого значення (void).
  • Func: представляє метод із нульовою або більшою кількістю вхідних параметрів і поверненим значенням. Останній генеричний параметр вказує тип поверненого значення.

Чому варто використовувати Action і Func?

Переваги у сучасному програмуванні на C#:

  1. Багаторазове використання коду: дозволяє передавати методи як параметри.
  2. Спрощене оброблення подій: полегшує реалізацію зворотних викликів та логіки, орієнтованої на події.
  3. Підтримка LINQ: забезпечує функціональні операції, як-от фільтрація (Where) та трансформація (Select).
  4. Динамічні конвеєри: дає змогу комбінувати методи під час виконання.

Практичні приклади

// Використання Action  
Action greet = name => Console.WriteLine($"Привіт, {name}!");  
greet("Аліса"); // Вивід: Привіт, Аліса!  

// Використання Func  
Func add = (a, b) => a + b;  
int sum = add(5, 10); // Повертає 15  
Console.WriteLine(sum); // Вивід: 15  

// Використання Action без повернення значення  
Action log = message => Console.WriteLine($"Лог: {message}");  
log("Операція завершена."); // Вивід: Лог: Операція завершена.  

// Використання Func для перетворення даних  
Func numberToString = number => $"Число: {number}";  
string result = numberToString(42); // Повертає "Число: 42"  
Console.WriteLine(result);  

// Ланцюжок кількох делегатів Action  
Action print = Console.WriteLine;  
Action exclaim = s => Console.WriteLine($"{s}!");  
Action combined = print + exclaim;  

combined("Привіт"); // Вивід: Привіт Привіт!  

// Покращення LINQ-запитів за допомогою Func  
var numbers = new List { 1, 2, 3, 4, 5 };  
var evenNumbers = numbers.Where(n => n % 2 == 0).ToList();  

evenNumbers.ForEach(n => Console.WriteLine(n)); // Вивід: 2 4

Поширені помилки та найкращі практики

  1. Уникайте великих лямбда-функцій, які погіршують читабельність.
// Неправильно  
Action print = x => {  
 if (x % 2 == 0) Console.WriteLine($"{x} парне");  
 else Console.WriteLine($"{x} непарне");  
};  

// Використовуйте іменовані методи  
void PrintEvenOdd(int x) {  
 Console.WriteLine(x % 2 == 0 ? $"{x} парне" : $"{x} непарне");  
}  
Action print = PrintEvenOdd;  
print(5); // Вивід: 5 непарне
  1. Уникайте захоплення змінних у циклах
// Неправильно  
List actions = new List();  
for (int i = 0; i < 3; i++) {  
 actions.Add(() => Console.WriteLine(i)); // Виведе: 3, 3, 3  
}  
actions.ForEach(action => action());  

// Правильно  
for (int i = 0; i < 3; i++) {  
 int localI = i;  
 actions.Add(() => Console.WriteLine(localI)); // Виведе: 0, 1, 2  
}  
actions.ForEach(action => action());

Висновок

Action та Func дають змогу використовувати функціональні принципи програмування в C#, покращуючи читабельність, багаторазовість і модульність коду. Незалежно від того, чи працюєте ви з подієорієнтованим кодом, запитами LINQ чи динамічними конвеєрами, ці делегати спрощують роботу з методами та зменшують обсяг шаблонного коду. Опанувавши їх можливості та уникаючи поширених помилок, ви зможете писати чистіший та ефективніший код на C#.

Перекладено з: Functional Programming in C#: Action and Func

Leave a Reply

Your email address will not be published. Required fields are marked *