Definir uma propriedade em um registro duas vezes
No C # 9, pode-se definir uma propriedade com o mesmo nome em um registro, tanto em seu construtor primário quanto em seu corpo:
record Cat(int PawCount)
{
public int PawCount { get; init; }
}
Este código é compilado sem erros.
Ao inicializar uma instância de tal registro, o valor fornecido ao construtor é completamente ignorado:
Console.WriteLine(new Cat(4));
Console.WriteLine(new Cat(4) { PawCount = 1 });
estampas
Cat { PawCount = 0 }
Cat { PawCount = 1 }
Este comportamento está correto ou é um bug? Se estiver correto, quais são os casos em que é útil?
Eu esperava que o compilador rejeitasse esse código com um erro como 'O tipo Cat
já contém uma definição para PawCount
' ou considerasse a propriedade no construtor e no corpo da mesma, executando sua inicialização a partir do construtor. A última variante pode ser útil para fornecer à propriedade um getter e / ou inicializador personalizado sem ter que reescrever todas as propriedades do registro posicional em seu corpo.
O comportamento real não faz sentido para mim.
Respostas
A maneira correta de fazer isso é:
record Cat(int PawCount)
{
public int PawCount { get; init; } = PawCount;
}
Isso é útil porque permite que você faça, por exemplo, validação
record Cat(int PawCount)
{
private int _pawCount;
public int PawCount {
get => _pawCount;
init => _pawCount = value < 0 ? throw new ArgumentException() : value;
} = PawCount;
}
A especificação para isso está aqui: https://github.com/dotnet/csharplang/blob/master/proposals/csharp-9.0/records.md#members-of-a-record-type
Os membros são sintetizados, a menos que um membro com uma assinatura "correspondente" seja declarado no corpo do registro ou um membro não virtual concreto acessível com uma assinatura "correspondente" seja herdado. Dois membros são considerados correspondentes se tiverem a mesma assinatura ou seriam considerados "ocultos" em um cenário de herança.
Portanto, como já existe uma propriedade com o mesmo nome do parâmetro, o compilador não sintetiza uma PawCount
propriedade e, portanto, ignora silenciosamente o parâmetro, a menos que você o use explicitamente.