Um problema comum na programação .NET com C# e VB é a quantidade de código repetitivo necessário para implementar objetos imutáveis. Diferentemente de uma classe normal, uma classe imutável necessita que cada propriedade possua um tipo definido de forma explícita e um construtor específico.
De forma a lidar com este problema, em uma especificação preliminar as linguagens C# e VB ganham o que está sendo chamado de "record class". Este novo recurso é essencialmente uma classe imutável definida unicamente pelo seu construtor. Veja um exemplo dessa especificação:
public record class Cartesian(double x: X, double y: Y);
Além do construtor, o compilador criará automaticamente:
- Uma propriedade somente leitura para cada parâmetro;
- Uma função Equals;
- Implementações de GetHashCode e ToString que sobreescrevem as implementações padrão;
- Um operador "is", conhecido como "Matches" no VB.
O operador "is/Matches" é utilizado em pattern matching - correspondência de padrões, tema abordado neste artigo da InfoQ. Além disso, classes "record" são muito parecidas com os tipos anônimos do C# (no VB, os tipos anônimos são mutáveis por padrão). A Microsoft está procurando formas de conciliar os dois conceitos, especialmente levando em conta a limitação da não exposição de tipos anônimos além de sua assembly atual.
Uma funcionalidade comum de tipos imutáveis é a habilidade de criar cópias do objeto com um ou mais campos atualizados. Apesar de ainda não fazer parte da especificação, esta opção está sendo considerada para o C#:
var x1 = new MyRecord(1, 2, 3); var x2 = x1 with B: 16; Console.WriteLine(x2) // prints something like "A = 1, B = 16, C = 3"
Estendendo classes Record
No exemplo da classe Cartesian, a declaração terminou com um ponto e vírgula. Isto indica que a classe não tem nenhum corpo além do que o fornecido pelo compilador
Ao invés do ponto e vírgula, é possível fornecer um conjunto de chaves, como em uma classe normal. Dessa forma o mesmo código é gerado pelo compilador, com a possibilidade de criar propriedades e métodos adicionais.
Outras limitações
Por enquanto, apenas classes "record" são suportadas. Na teoria, structs do tipo record também poderiam ser adicionadas utilizando a mesma sintaxe e conceitos.
Preocupações de bibliotecas
Uma grande limitação dos tipos imutáveis no .NET é a falta de bibliotecas que suportem esta funcionalidade. Como exemplo, entre as atividades rotineiras de um desenvolvedor, uma das mais comuns é solicitar a um ORM objetos do banco de dados, os quais podem ser serializados como SOAP-XML ou JSON para comunicação com o cliente da aplicação.
Atualmente, a maioria dos ORMs e serializadores não tem suporte para tipos imutáveis. Ao invés disso, eles assumem que sempre irá existir um construtor sem parâmetros e propriedades mutáveis. Se isso não for alterado nos frameworks mais populares, as classes record terão pouco uso na maioria dos projetos.
Para mais informações sobre o assunto, veja o projeto da especificação Pattern Matching para C#. Um protótipo deve estar disponível em algumas semanas.