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
thisse o projeto ainda estiver em versão anterior ou se você quiser máxima compatibilidade.