Definición de una propiedad en un registro dos veces

Dec 02 2020

En C # 9, se puede definir una propiedad con el mismo nombre en un registro tanto en su constructor principal como en su cuerpo:

record Cat(int PawCount)
{
    public int PawCount { get; init; }
}

Este código se compila sin errores.

Al inicializar una instancia de dicho registro, el valor proporcionado al constructor se ignora por completo:

Console.WriteLine(new Cat(4));
Console.WriteLine(new Cat(4) { PawCount = 1 });

huellas dactilares

Cat { PawCount = 0 }
Cat { PawCount = 1 }

¿Este comportamiento es correcto o es un error? Si es correcto, ¿cuáles son los casos en los que es útil?

Esperaba que el compilador rechazara este código con un error como 'El tipo Catya contiene una definición para PawCount' o considerara la propiedad en el constructor y en el cuerpo de la misma manera, realizando su inicialización desde el constructor. La última variante podría ser útil para proporcionar a la propiedad un captador y / o inicializador personalizado sin tener que reescribir todas las propiedades del registro posicional en su cuerpo.

El comportamiento real no tiene sentido para mí.

Respuestas

9 YairHalberstadt Dec 02 2020 at 22:10

La forma correcta de hacer esto es:

record Cat(int PawCount)
{
    public int PawCount { get; init; } = PawCount;
}

Esto es útil ya que le permite hacer, por ejemplo, validación

record Cat(int PawCount)
{
    private int _pawCount;
    public int PawCount {
        get => _pawCount;
        init => _pawCount = value < 0 ? throw new ArgumentException() : value; 
    } = PawCount;
}

La especificación para esto está aquí: https://github.com/dotnet/csharplang/blob/master/proposals/csharp-9.0/records.md#members-of-a-record-type

Los miembros se sintetizan a menos que se declare un miembro con una firma "coincidente" en el cuerpo del registro o se herede un miembro no virtual concreto accesible con una firma "coincidente". Se considera que dos miembros coinciden si tienen la misma firma o se considerarían "ocultos" en un escenario de herencia.

Entonces, dado que ya existe una propiedad con el mismo nombre que el parámetro, el compilador no sintetizará una PawCountpropiedad, por lo que simplemente ignorará el parámetro en silencio a menos que lo use usted mismo explícitamente.