Timp de două decenii, una dintre cele mai frustrante limitări din C# a fost imposibilitatea de a scrie algoritmi generici peste tipuri numerice: dacă scriați o funcție T CalculeazaSuma<T>(T a, T b), codul nu compila deoarece operatorul + nu era definit pe un parametru generic T fără constrângere specifică.
Începând cu C# 11 și .NET 7, introducerea Membrilor Statici Virtuali în Interfețe (Static Abstract Members in Interfaces) a deblocat facilitatea Generic Math prin interfața universală INumber<T>.
using System.Numerics;
public class AlgoritmiMatematici
{
// O singură funcție generică funcționează identic pentru int, double, decimal, float etc.:
public static T CalculeazaSumaTotala<T>(ReadOnlySpan<T> numere) where T : INumber<T>
{
T suma = T.Zero; // Valoarea neutră 0 definită static pe tipul T!
foreach (T valoare in numere)
{
suma += valoare; // Operatorul '+' este validat la compilare prin interfață!
}
return suma;
}
}
public class Program
{
public static void Main()
{
int[] numereIntregi = [10, 20, 30];
int sumaInt = AlgoritmiMatematici.CalculeazaSumaTotala<int>(numereIntregi);
double[] numereReale = [1.5, 2.5, 3.5];
double sumaDouble = AlgoritmiMatematici.CalculeazaSumaTotala<double>(numereReale);
Console.WriteLine($"Suma int: {sumaInt}, Suma double: {sumaDouble}");
}
}
Cum Funcționează Sub Capotă?
Interfața INumber<T> declară operatorii matematici ca metode statice abstracte:
public interface IAdditionOperators<TSelf, TOther, TResult>
{
static abstract TResult operator +(TSelf left, TOther right);
}
La momentul compilării JIT, RyuJIT specializează funcția pentru tipul concret de procesor (monomorfizare nativă), generând instrucțiuni de asamblare identice ca viteză cu codul scris manual pentru fiecare tip în parte.