Ce face Constrângeri generice (where T : ...)
Fără constrângeri, în interiorul unei metode generice poți folosi doar ce are orice object. Clauza where T : ... promite compilatorului ce știe tipul și îți dă acces la membrii respectivi: cu where T : IComparable<T> poți apela CompareTo, cu where T : new() poți scrie new T().
Constrângerile uzuale sunt: class (tip referință), struct (tip valoare nenul), notnull, unmanaged, new() (constructor public fără parametri, pus ultimul), o clasă de bază sau una ori mai multe interfețe. Din C# 13 există și allows ref struct.
Fiecare parametru de tip are propria clauză where. Un argument care nu respectă constrângerea dă eroare la compilare, nu la rulare.
Parametri
| Parametru | Descriere |
|---|---|
where T : class / struct |
Tip referință, respectiv tip valoare. |
where T : IInterfata |
T trebuie să implementeze interfața; îi poți apela membrii. |
where T : Baza |
T este Baza sau o clasă derivată. |
where T : new() |
T are constructor public fără parametri. |
Exemple
Exemplul 1: Maxim generic cu IComparable
Console.WriteLine(Maxim(3, 9));
Console.WriteLine(Maxim("Cluj", "Arad"));
Console.WriteLine(Maxim(new DateOnly(2026, 1, 5), new DateOnly(2025, 12, 31)).Year);
static T Maxim<T>(T a, T b) where T : IComparable<T> =>
a.CompareTo(b) >= 0 ? a : b;
Rezultat
9
Cluj
2026
Exemplul 2: Depozit generic cu interfață și new()
var repo = new Depozit<Produs>();
repo.Adauga(new Produs { Id = 1, Nume = "Laptop" });
var gol = repo.CreeazaGol();
Console.WriteLine(repo.Cauta(1)?.Nume);
Console.WriteLine(repo.Cauta(2)?.Nume ?? "nu există");
Console.WriteLine(gol.Id);
interface IEntitate { int Id { get; } }
class Produs : IEntitate
{
public int Id { get; set; }
public string Nume { get; set; } = "";
}
class Depozit<T> where T : class, IEntitate, new()
{
private readonly List<T> _elemente = [];
public void Adauga(T e) => _elemente.Add(e);
public T? Cauta(int id) => _elemente.FirstOrDefault(e => e.Id == id);
public T CreeazaGol() => new T();
}
Rezultat
Laptop
nu există
0
Greșeli frecvente
new()trebuie să fie ultima constrângere, iarclass/structprima.- Operatorii
<,+sau==nu merg pe unToarecare. Pentru comparații foloseșteIComparable<T>; pentru aritmetică, interfețele de generic math (INumber<T>). - Cu tipurile nullable activate,
where T : classcere un tip referință fără?(altfel primești avertisment), iarwhere T : class?acceptă șistring?.
Comenzi înrudite
Metode de extensie (this): Adaugă metode unui tip existent (string, int, interfețe) fără să-l modifici: metodă statică cu this în fața primului parametru.IEnumerable<T> și yield return: IEnumerable<T> este orice secvență care se poate parcurge cu foreach; yield return produce elementele pe rând, doar când sunt cerute.