Membri de extensie: blocul extension (C# 14) în C# (.NET)

C# 14 aduce blocul extension: proprietăți de extensie, metode și proprietăți statice de extensie, nu doar metode de instanță.

Sintaxă C#
static class Ext { extension(string s) { public bool EsteGol => s.Length == 0; } extension(string) { public static string Gol => ""; } }

Ce face Membri de extensie: blocul extension (C# 14)

Blocul extension(Tip receptor) se scrie într-o static class negenerică de nivel superior. Toți membrii din bloc extind tipul dat, iar numele receptorului (de exemplu s) este disponibil în fiecare membru de instanță. În bloc poți declara metode, proprietăți și operatori.

Când blocul are doar membri statici, receptorul nu are nevoie de nume: extension(string) { public static ... }. Membrii statici se apelează pe tip, ca și cum ar aparține lui: string.Gol.

Pentru tipuri generice, parametrul de tip se pune pe bloc: extension<T>(IEnumerable<T> sursa). Metodele de extensie vechi (cu this) și cele noi generează același cod, deci poți migra fără să strici apelurile existente.

Exemple

Exemplul 1: Proprietăți de extensie și membru static

string nume = "Ana";
Console.WriteLine(nume.Initiala);
Console.WriteLine("".EsteGol);
Console.WriteLine(string.Separator);

static class TextExtensii
{
    extension(string s)
    {
        public string Initiala => s.Length > 0 ? s[..1] : "";
        public bool EsteGol => s.Length == 0;
    }

    extension(string)
    {
        public static string Separator => "---";
    }
}

Rezultat

A
True
---

Exemplul 2: Bloc generic pentru colecții

T și constrângerea lui se declară pe bloc și sunt disponibile în toți membrii.

int[] note = [9, 4, 10];
List<string> goala = [];

Console.WriteLine(note.CatePeste(8));
Console.WriteLine(goala.EsteGoala);
Console.WriteLine(note.EsteGoala);

static class ColectiiExtensii
{
    extension<T>(IEnumerable<T> sursa) where T : IComparable<T>
    {
        public bool EsteGoala => !sursa.Any();

        public int CatePeste(T prag) =>
            sursa.Count(x => x.CompareTo(prag) > 0);
    }
}

Rezultat

2
True
False

Greșeli frecvente

  • Blocul extension într-o clasă generică, nestatică sau imbricată nu se compilează.
  • Toți membrii din aceeași clasă statică trebuie să aibă semnături diferite, chiar dacă sunt în blocuri extension diferite: blocul nu creează un domeniu de nume separat.
  • Necesită C# 14, adică SDK-ul .NET 10 (sau <LangVersion>14</LangVersion>).

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.
  • Clase și membri static: Membrii static aparțin tipului, nu unui obiect; o static class conține doar membri statici și nu poate fi instanțiată.
  • Constrângeri generice (where T : ...): Clauza where limitează tipurile acceptate de un generic (class, struct, new(), o interfață sau clasă de bază) ca să le poți folosi membrii.