Ce face Func, Action și Predicate
Func<T1, ..., TResult> reprezintă o funcție cu până la 16 parametri, iar ultimul argument generic este tipul returnat: Func<string, int> primește un string și dă un int. Action<T1, ...> este la fel, dar fără valoare returnată; Action simplu nu are parametri.
Predicate<T> este echivalent cu Func<T, bool> și apare în metode mai vechi precum List<T>.FindAll și RemoveAll. Cele două tipuri nu sunt interschimbabile direct, deși au aceeași formă.
Primind un Func sau un Action ca parametru, o metodă își lasă o parte din comportament la alegerea celui care o apelează, fără să declari un tip de delegat propriu.
Parametri
| Parametru | Descriere |
|---|---|
Func<TResult> |
Fără parametri, returnează TResult. |
Func<T, TResult> |
Un parametru; ultimul tip generic este mereu cel returnat. |
Action<T> |
Un parametru, fără valoare returnată. |
Predicate<T> |
Un parametru, returnează bool. |
Exemple
Exemplul 1: Metodă care primește comportamentul ca parametru
List<int> preturi = [120, 45, 300, 80];
Console.WriteLine(Aplica(preturi, p => p * 2));
Console.WriteLine(Aplica(preturi, p => p - p / 10));
Action<string> jurnal = mesaj => Console.WriteLine($"[log] {mesaj}");
jurnal("Calcul terminat");
static string Aplica(List<int> valori, Func<int, int> transformare)
{
var rezultat = new List<int>();
foreach (int v in valori)
rezultat.Add(transformare(v));
return string.Join(" ", rezultat);
}
Rezultat
240 90 600 160
108 41 270 72
[log] Calcul terminat
Exemplul 2: Predicate cu FindAll și RemoveAll
List<string> orase = ["Iași", "Arad", "Cluj", "Alba Iulia"];
Predicate<string> incepeCuA = o => o.StartsWith('A');
Console.WriteLine(string.Join(", ", orase.FindAll(incepeCuA)));
int sterse = orase.RemoveAll(incepeCuA);
Console.WriteLine($"{sterse} șterse, rămân: {string.Join(", ", orase)}");
Func<string> ora = () => "12:00";
Console.WriteLine(ora());
Rezultat
Arad, Alba Iulia
2 șterse, rămân: Iași, Cluj
12:00
Greșeli frecvente
- Inversarea ordinii la
Func: înFunc<int, string>parametrul esteint, iar rezultatulstring. - Apelarea unui delegat
nullaruncăNullReferenceException. Pentru parametri opționali foloseștecallback?.Invoke(x). - Un
Predicate<T>nu se poate da direct unei metode LINQ care cereFunc<T, bool>; scrie lambda din nou sau foloseștep.Invokeca grup de metode.
Comenzi înrudite
Expresii lambda (=>): O funcție scurtă, fără nume, scrisă pe loc: parametri => rezultat. Se folosește în LINQ, la evenimente și oriunde se cere un delegat.delegate: Un delegat este un tip care ține o referință spre o metodă cu o anumită semnătură; poate ține mai multe metode (multicast).event și EventHandler: Un eveniment anunță abonații când se întâmplă ceva; din afara clasei te poți doar abona (+=) sau dezabona (-=).