Start Debugging

C# 14: a palavra-chave field e propriedades respaldadas por field

C# 14 introduz a palavra-chave contextual field nos acessadores de propriedades, permitindo adicionar lógica personalizada às auto-properties sem declarar um campo de apoio separado.

C# 14 introduz uma nova palavra-chave contextual, field, que pode ser usada dentro dos acessadores de uma propriedade (os blocos get, set ou init) para se referir ao armazenamento de apoio da propriedade. Em termos simples, field é um marcador que representa a variável oculta onde o valor de uma propriedade é guardado. Esta palavra-chave permite adicionar lógica personalizada a propriedades implementadas automaticamente sem declarar manualmente um campo privado separado. Ela apareceu primeiro em prévia no C# 13 (exigindo .NET 9 com a versão do idioma definida como preview) e é oficialmente parte da linguagem no C# 14.

Por que isso é útil? Antes do C# 14, se você quisesse adicionar lógica (como validação ou notificação de mudança) a uma propriedade, precisava transformá-la em uma propriedade completa com um campo privado de apoio. Isso significava mais código repetitivo e o risco de outros membros da classe usarem esse campo diretamente, contornando a lógica da propriedade. A nova palavra-chave field resolve esses problemas deixando o compilador gerar e gerenciar o campo de apoio para você, enquanto você simplesmente usa field no código da propriedade. O resultado são declarações de propriedade mais limpas e fáceis de manter, evitando que o armazenamento de apoio “vaze” para o restante do escopo da sua classe.

Benefícios e cenários de uso de field

A palavra-chave field foi introduzida para tornar as declarações de propriedade mais concisas e menos propensas a erros. Veja os principais benefícios e cenários em que ela é útil:

No geral, field melhora a legibilidade e a manutenibilidade ao remover código redundante e focar apenas no comportamento personalizado de que você precisa. É conceitualmente similar a como a palavra-chave value funciona em um setter (representando o valor que está sendo atribuído); aqui, field representa o armazenamento subjacente da propriedade.

Antes vs. depois: campo de apoio manual vs. palavra-chave field

Para ver a diferença, vamos comparar como você declararia uma propriedade que impõe alguma regra antes do C# 14 e depois, usando a nova palavra-chave field.

Cenário: Suponha que queremos uma propriedade Hours que nunca possa ser definida como um número negativo. Em versões mais antigas do C#, faríamos o seguinte:

Antes do C# 14, usando um campo de apoio manual:

public class TimePeriodBefore
{
    private double _hours;  // backing field

    public double Hours
    {
        get { return _hours; }
        set 
        {
            if (value < 0)
                throw new ArgumentOutOfRangeException(nameof(value), "Value must not be negative");
            _hours = value;
        }
    }
}

Neste código pré-C#14, tivemos que introduzir um campo privado _hours para guardar o valor. O getter da propriedade retorna esse campo, e o setter realiza uma verificação antes de atribuir a _hours. Funciona, mas é verboso: há código extra para declarar e gerenciar _hours, e _hours é acessível em qualquer parte da classe (ou seja, outros métodos podem escrever em _hours e contornar a lógica de validação se não houver cuidado).

A partir do C# 14, usando a palavra-chave field:

public class TimePeriod
{
    public double Hours
    {
        get;  // auto-implemented getter (compiler provides it)
        set => field = (value >= 0) 
            ? value 
            : throw new ArgumentOutOfRangeException(nameof(value), "Value must not be negative");
    }
}

Aqui, a propriedade Hours é declarada sem campo de apoio explícito. Usamos get; sem corpo, indicando um getter automático, e fornecemos um corpo para set que usa field. A expressão field = ... dentro do setter diz ao compilador para atribuir ao campo de apoio da propriedade. O compilador gerará automaticamente um campo privado nos bastidores e implementará o acessador get para retornar esse campo. No setter acima, se o value for negativo, lançamos uma exceção; caso contrário, atribuímos ao field (que o armazena). Não precisamos declarar _hours por nossa conta, e nem é preciso escrever o corpo do getter: o compilador faz isso por nós. O resultado é uma definição de propriedade mais concisa com o mesmo comportamento.

Repare como a versão em C# 14 é bem mais limpa:

Você também pode usar field em um acessador get, se necessário. Por exemplo, para implementar inicialização preguiçosa, você poderia fazer algo como:

public string Name 
{
    get => field ??= "Unknown";
    set => field = value;
}

Nesse caso, na primeira vez que Name é acessado, se ele não estiver definido, o getter atribui um valor padrão "Unknown" ao campo de apoio e o retorna. As próximas leituras ou qualquer atribuição usarão o mesmo field. Sem esse recurso, você precisaria de um campo privado e mais código no getter para conseguir o mesmo comportamento.

Como o compilador lida com a palavra-chave field

Quando você usa field dentro de um acessador de propriedade, o compilador gera silenciosamente um campo de apoio oculto para essa propriedade (muito parecido com o que ele faz para uma propriedade auto-implementada). Você nunca verá esse campo no seu código-fonte, mas o compilador dá a ele um nome interno (por exemplo, algo como <Hours>k__BackingField) e o usa para armazenar o valor da propriedade. Veja o que acontece nos bastidores:

TLDR; o compilador gera um campo de apoio privado e conecta seus acessadores de propriedade para usá-lo. Você obtém a funcionalidade de uma propriedade completa com uma fração do código. A propriedade continua, do ponto de vista da implementação, sendo uma auto-property real: você simplesmente ganhou um gancho para injetar lógica nela.

Regras de sintaxe e uso de field

Ao usar a palavra-chave field, lembre-se das seguintes regras e limitações:

Resumindo: use field dentro dos acessadores da sua propriedade para se referir ao armazenamento oculto dessa propriedade, e em nenhum outro lugar. Siga as regras normais de escopo do C# para tudo que estiver fora de propriedades.

Lidando com conflitos de nomes (quando você tem sua própria variável field)

Como field não era uma palavra reservada em versões mais antigas do C#, é possível (embora incomum) que algum código tenha usado “field” como nome de variável ou de campo. Com a introdução da palavra-chave contextual field em acessadores, esse código pode ficar ambíguo ou quebrar. O design da linguagem leva isso em conta:

private int field = 10; // a field unfortunately named "field" 
public int Example
{
    get { return @field; } // use @field to return the actual field 
    set { @field = value; } // or this.field = value; either works 
}

Referências

  1. field – Field backed property declarations
  2. C# Feature Proposal Notes – field keyword in properties”
  3. What’s new in C# 14

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< Voltar