Start Debugging

C# 14: la palabra clave field y las propiedades respaldadas por field

C# 14 introduce la palabra clave contextual field en los accesores de propiedades, lo que te permite añadir lógica personalizada a las auto-properties sin declarar un campo de respaldo aparte.

C# 14 introduce una nueva palabra clave contextual, field, que se puede usar dentro de los accesores de una propiedad (los bloques get, set o init) para referirse al almacenamiento de respaldo de la propiedad. En términos sencillos, field es un marcador que representa la variable oculta donde se almacena el valor de una propiedad. Esta palabra clave te permite añadir lógica personalizada a las propiedades implementadas automáticamente sin declarar manualmente un campo privado aparte. Apareció primero como vista previa en C# 13 (requería .NET 9 con la versión del lenguaje en preview) y, oficialmente, forma parte del lenguaje en C# 14.

¿Por qué es útil? Antes de C# 14, si querías añadir lógica (como validación o notificación de cambios) a una propiedad, tenías que convertirla en una propiedad completa con un campo privado de respaldo. Eso suponía más código repetitivo y el riesgo de que otros miembros de la clase usaran ese campo directamente, saltándose la lógica de la propiedad. La nueva palabra clave field aborda estos problemas dejando que el compilador genere y administre el campo de respaldo por ti, mientras tú simplemente usas field en el código de tu propiedad. El resultado son declaraciones de propiedad más limpias y mantenibles, evitando que el almacenamiento de respaldo “se filtre” al resto del ámbito de tu clase.

Beneficios y casos de uso de field

La palabra clave field se introdujo para hacer las declaraciones de propiedades más concisas y menos propensas a errores. Estos son los principales beneficios y escenarios donde resulta útil:

En conjunto, field mejora la legibilidad y la mantenibilidad eliminando código redundante y centrando la atención solo en el comportamiento personalizado que necesitas. Es conceptualmente similar a cómo funciona la palabra clave value en un setter (representando el valor que se está asignando); aquí field representa el almacenamiento subyacente de la propiedad.

Antes vs. después: campo de respaldo manual vs. la palabra clave field

Para ver la diferencia, comparemos cómo declararías una propiedad que aplica una regla antes de C# 14 y después usando la nueva palabra clave field.

Escenario: Supón que queremos una propiedad Hours que nunca se pueda asignar a un número negativo. En versiones anteriores de C# haríamos lo siguiente:

Antes de C# 14, usando un campo de respaldo 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;
        }
    }
}

En este código previo a C# 14, tuvimos que introducir un campo privado _hours para guardar el valor. El getter de la propiedad devuelve este campo y el setter realiza una comprobación antes de asignar a _hours. Funciona, pero es verboso: hay código extra para declarar y administrar _hours, y _hours es accesible en cualquier parte de la clase (lo que significa que otros métodos podrían escribir en _hours y saltarse la lógica de validación si no se tiene cuidado).

Desde C# 14, usando la palabra clave 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");
    }
}

Aquí, la propiedad Hours se declara sin un campo de respaldo explícito. Usamos get; sin cuerpo, indicando un getter automático, y proporcionamos un cuerpo para set que usa field. La expresión field = ... dentro del setter le dice al compilador que asigne al campo de respaldo de la propiedad. El compilador generará automáticamente un campo privado en segundo plano e implementará el accesor get para devolver ese campo. En el setter de arriba, si el value es negativo, lanzamos una excepción; de lo contrario, lo asignamos a field (que lo almacena). No tuvimos que declarar _hours nosotros mismos, y tampoco hace falta escribir el cuerpo del getter: el compilador hace eso por nosotros. El resultado es una definición de propiedad más concisa con el mismo comportamiento.

Observa lo mucho más limpia que es la versión de C# 14:

También puedes usar field en un accesor get si lo necesitas. Por ejemplo, para implementar una inicialización perezosa, podrías hacer algo como:

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

En este caso, la primera vez que se accede a Name, si no se había asignado, el getter asigna un valor por defecto "Unknown" al campo de respaldo y lo devuelve. Las siguientes lecturas o cualquier asignación usarán el mismo field. Sin esta característica, habrías necesitado un campo privado y más código en el getter para conseguir el mismo comportamiento.

Cómo maneja el compilador la palabra clave field

Cuando usas field dentro de un accesor de propiedad, el compilador genera silenciosamente un campo de respaldo oculto para esa propiedad (muy parecido a cómo lo hace para una propiedad auto-implementada). Nunca verás este campo en tu código fuente, pero el compilador le da un nombre interno (por ejemplo, algo como <Hours>k__BackingField) y lo usa para almacenar el valor de la propiedad. Esto es lo que ocurre por debajo:

TLDR; el compilador genera un campo de respaldo privado y conecta tus accesores de propiedad para usarlo. Obtienes la funcionalidad de una propiedad completa con una fracción del código. La propiedad sigue siendo, desde el punto de vista de implementación, una auto-propiedad real; simplemente conseguiste un gancho para inyectar lógica.

Reglas de sintaxis y uso de field

Al usar la palabra clave field, ten en cuenta las siguientes reglas y limitaciones:

Dicho de forma simple: usa field dentro de los accesores de tu propiedad para referirte al almacenamiento oculto de esa propiedad, y no en ningún otro sitio. Sigue las reglas normales de ámbito de C# para todo lo que esté fuera de las propiedades.

Manejo de conflictos de nombres (cuando tienes tu propia variable field)

Como field no era una palabra reservada en versiones anteriores de C#, es posible (aunque poco habitual) que algún código haya usado “field” como nombre de variable o de campo. Con la introducción de la palabra clave contextual field en los accesores, ese código podría volverse ambiguo o romperse. El diseño del lenguaje lo tiene en cuenta:

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 
}

Referencias

  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.

< Volver