Assinar
Voltar
Backend

C# 14 na prática: extension members e a palavra-chave field que enxugam seu código

O C# 14, que chega junto com o .NET 10, traz duas novidades que mudam o dia a dia de quem escreve backend: os novos membros de extensão e a palavra-chave field para propriedades. Veja como usar sem susto.

{}

O C# 14 é a versão da linguagem que acompanha o .NET 10, e você pode experimentá-la com o SDK do .NET 10 ou o Visual Studio mais recente. Em vez de uma lista gigante de recursos, quero focar em duas mudanças que realmente aparecem no código de todo dia em projetos backend: os novos extension members (membros de extensão) e a palavra-chave contextual field. As duas atacam o mesmo inimigo: o código repetitivo que a gente escreve no automático.

Extension members: além dos métodos de extensão

Métodos de extensão existem no C# há muito tempo e são a base de bibliotecas como o LINQ. O problema é que, até agora, só dava para estender um tipo com métodos. Se você quisesse uma “propriedade de extensão” ou um operador, não tinha jeito. O C# 14 resolve isso com uma sintaxe nova: o bloco extension.

A ideia é agrupar, dentro de uma classe estática, um bloco que declara o tipo receptor uma única vez. Compare a forma tradicional com a nova:

Antes

public static class EnumerableExtensions
{
    public static bool IsEmpty<T>(this IEnumerable<T> source)
        => !source.Any();
}

Agora, com bloco de extensão

public static class EnumerableExtensions
{
    extension<T>(IEnumerable<T> source)
    {
        // propriedade de extensão
        public bool IsEmpty => !source.Any();

        // método de extensão
        public IEnumerable<T> WhereNotNull()
            => source.Where(x => x is not null);
    }
}

Repare que o receptor (source) e o parâmetro genérico saem da assinatura de cada método e passam para o cabeçalho do bloco. Some-se a isso o fato de que agora dá para declarar uma propriedade (IsEmpty) chamada como se fosse instância: lista.IsEmpty. Fica muito mais natural do que lista.IsEmpty().

Há também os membros estáticos de extensão. Você declara um bloco que menciona apenas o tipo receptor, sem uma variável, e passa a poder adicionar métodos, propriedades e até operadores estáticos ao próprio tipo:

extension<T>(IEnumerable<T>)
{
    public static IEnumerable<T> operator +(
        IEnumerable<T> left, IEnumerable<T> right)
        => left.Concat(right);
}

A grande sacada é que a sintaxe antiga continua válida. Você adota os blocos de extensão quando fizer sentido, sem precisar reescrever tudo.

Vale um aviso honesto: nem todo método de extensão migra de forma mecânica para a nova sintaxe, e o suporte das ferramentas foi amadurecendo ao longo das prévias do .NET 10. Ou seja, adote com calma em bibliotecas já consolidadas.

A palavra-chave field: menos campo de apoio na mão

Quem valida valor dentro de um set conhece a dança: declarar um campo privado _algumaCoisa só para dar suporte a uma propriedade. O C# 14 introduz a palavra-chave contextual field, que representa um campo de apoio gerado pelo próprio compilador.

Antes

private string _message;
public string Message
{
    get => _message;
    set => _message = value
        ?? throw new ArgumentNullException(nameof(value));
}

Agora

public string Message
{
    get;
    set => field = value
        ?? throw new ArgumentNullException(nameof(value));
}

O get; continua automático e só o set ganha lógica, referenciando o campo sintetizado via field. Você pode escrever corpo para um ou para os dois acessadores.

Um detalhe de convivência: se o seu tipo já tiver um símbolo chamado field, pode haver confusão. Nesses casos, use @field ou this.field para desambiguar, ou simplesmente renomeie o símbolo antigo.

Bônus: atribuição condicional a nulo

Ainda no espírito de enxugar guardas repetitivas, os operadores ?. e ?[] agora podem aparecer no lado esquerdo de uma atribuição. Em vez de checar nulo antes de atribuir:

if (customer is not null)
    customer.Order = GetCurrentOrder();

Você escreve:

customer?.Order = GetCurrentOrder();

O lado direito só é avaliado quando o receptor não é nulo, então GetCurrentOrder() nem chega a ser chamado se customer for nulo. Também funciona com atribuições compostas como +=, mas não com ++ e --.

Vale a pena migrar?

Nenhum desses recursos é revolucionário isoladamente, mas juntos eles reduzem ruído e deixam a intenção do código mais evidente, o que ajuda em manutenção e revisão. Para times que já estão no .NET 10, os membros de extensão e o field são adoções de baixo risco e retorno imediato em legibilidade. Comece por código novo e por utilitários pequenos antes de mexer em bibliotecas críticas.

Fontes

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *