Skip to main content

extension | .NET 10, CSharp 14 | CSharp

  • extension | .NET 10, CSharp 14 | CSharp

O “novo extension” do C# é o recurso de extension members / extension blocks, introduzido no C# 14. Ele é uma evolução dos antigos extension methods e permite declarar extensões com uma sintaxe mais organizada, além de suportar métodos, propriedades e extensões sobre o tipo em si, não só sobre a instância.

Antes

A sintaxe clássica continua válida:

public static class StringExtensions
{
public static bool IsNullOrWhiteSpaceEx(this string? value)
=> string.IsNullOrWhiteSpace(value);
}

Uso:

string? nome = "Adolfo";

bool vazio = nome.IsNullOrWhiteSpaceEx();

Essa forma antiga usa this no primeiro parâmetro para indicar o tipo estendido. Ela ainda funciona, mesmo com a chegada dos extension blocks.

Nova forma

Com o novo modelo, você escreve assim:

public static class StringExtensions
{
extension(string? value)
{
public bool IsNullOrWhiteSpaceEx()
=> string.IsNullOrWhiteSpace(value);
}
}

Uso:

string? nome = "Adolfo";

bool vazio = nome.IsNullOrWhiteSpaceEx();

O extension(...) define o receiver da extensão. Dentro dele, você coloca os membros que passam a “parecer” fazer parte do tipo. Esse bloco deve ficar dentro de uma classe static, não genérica e não aninhada.

Exemplo útil com string

public static class StringExtensions
{
extension(string value)
{
public string OnlyNumbers()
=> new string(value.Where(char.IsDigit).ToArray());

public bool HasValue()
=> !string.IsNullOrWhiteSpace(value);
}
}

Uso:

string cpf = "123.456.789-00";

Console.WriteLine(cpf.OnlyNumbers()); // 12345678900
Console.WriteLine(cpf.HasValue()); // true

Exemplo útil com DateTime

public static class DateTimeExtensions
{
extension(DateTime value)
{
public bool IsWeekend()
=> value.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday;
}
}

Uso:

bool fimDeSemana = DateTime.Now.IsWeekend();

O que melhorou de fato

A principal melhora é organização. Em vez de espalhar vários métodos estáticos com this, você agrupa tudo dentro de um bloco por tipo. Além disso, o C# 14 passou a permitir propriedades de extensão e também membros que estendem o tipo estático, não apenas a instância.

Exemplo conceitual de propriedade:

public static class StringExtensions
{
extension(string value)
{
public int WordCount
=> value.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
}
}

Uso:

string texto = "ola mundo csharp";
Console.WriteLine(texto.WordCount);

Quando usar

Use esse recurso quando você quer:

  • adicionar comportamento a tipos que você não controla;
  • deixar chamadas mais fluídas;
  • centralizar extensões por tipo;
  • evitar helpers soltos como StringHelper.Foo(x).

Quando não usar

Evite quando:

  • o nome do método pode confundir com API nativa;
  • a regra é muito específica do seu domínio e não do tipo;
  • a extensão esconde custo alto ou efeitos colaterais.

Regra prática

Para código novo, eu usaria assim:

  • extension blocks quando o projeto já estiver em C# 14+;
  • sintaxe antiga com this se o projeto ainda estiver em versão anterior ou se você quiser máxima compatibilidade.