C# 9.0 - Init-only Properties


 Hoje vamos apresentar o novo recurso do C# 9.0 chamado Init-only properties que pode ser usado para criar propriedades imutáveis sem usar um construtor.

Na versão 3.0 do C# foi introduzido a sintaxe Object Initializer, uma nova maneira de inicializar um objeto de uma classe ou coleção.

Este recurso permite que você atribua valores para os campos ou propriedades no momento da criação do objeto sem invocar um construtor.

Importante:  Para usar o C# 9.0 e o recurso Init-only properties você precisa instalar o .NET 5.0 RC1 e o Visual Studio 2019 Preview. O arquivo de projeto .csproj deve possuir a seguinte definição:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>  
    <OutputType>Exe</OutputType>
         <TargetFramework>net5.0</TargetFramework>
        <LangVersion>9.0</LangVersion>

  </PropertyGroup>

</Project>

Dada uma classe Cliente com duas propriedades Nome e Email:

Podemos criar um objeto Cliente usando o recurso object initializer assim:



O objetct initializer chama o construtor padrão e então inicializa as duas propriedades chamando seus setters.

Criando o propriedade Imutáveis

O problema com os inicializadores de objeto é que eles não permitem que você crie propriedades imutáveis - pelo menos não antes do C# 9.0.

As propriedades imutáveis são propriedades que você não pode alterar depois de criar o objeto.

Mas em nosso exemplo, você pode alterar a propriedade Nome de um cliente a qualquer momento após criar o objeto Cliente conforme mostrado abaixo:

E como tornar essa propriedade imutável ?

Para tornar as propriedades imutáveis podemos fazer assim:

  1. Criar um construtor parametrizado atribuindo valores às propriedades;
  2. Remover os setters das propriedades definindo apenas os getters;

Agora temos propriedades automáticas get-only e elas só podem ser inicializadas diretamente ou via construtor. Essa é a mesma lógica dos campos somente leitura, eles também podem ser inicializados diretamente ou em um construtor.

Agora ao tentar atribuir um valor à qualquer propriedade teremos um erro :

 Com isso as propriedades Nome e Email agora são imutáveis mas para poder fazer isso tivemos que definir um construtor.

Usando Init-only properties

Com o C# 9.0 podemos criar propriedades imutáveis sem ter que criar um construtor usando o recurso init-only properties.

Para isso basta substituir o set da propriedade pela palavra init:

Agora não será possível alterar o valor de uma propriedade já inicializada conforme mostra o código:

A palavra-chave init é usada para definir um tipo especial de acessador set e são agora chamadas de propriedades  init-only e isso significa que você só pode inicializar essas propriedades no construtor ou diretamente como abaixo:

Cabe destacar que  os valores para propriedades init-only não são necessários, eles são opcionais.

Você também pode definir apenas as propriedades desejadas, como faria com propriedades automáticas normais.

No exemplo podemos definir apenas a propriedade Nome :

Porém, como usamos propriedades definidas com init, você não tem chance de definir a propriedade Email após esta instrução, pois as propriedades são imutáveis. Se tentar vai obter um erro como mostrado acima.

Definição de campos somente leitura

Como o acessador init de uma propriedade init-only é chamado durante a inicialização do objeto, é permitido definir campos somente leitura no acessador init, exatamente da mesma maneira que você poderia defini-los em um construtor. Isso é útil se você deseja fazer verificações no valor da propriedade atribuída.

Por exemplo, atribuir nulo ou espaço em branco não faz muito sentido para as propriedades Nome e Email.

Assim, você pode criar a classe Cliente como abaixo e definir campos somente leitura nos acessadores init das propriedades.

As propriedades ainda são imutáveis, mas se você atribuir nulo ou espaço em branco em um inicializador de objeto - essa é a única maneira de definir essas propriedades dessa classe, já que nenhum construtor está definido - você vai obter um erro do tipo ArgumentException.

Dessa forma as propriedades init-only permitem que você crie propriedades imutáveis sem definir um construtor que leva os valores iniciais da propriedade sendo um recurso útil se você planejar trabalhar com dados imutáveis no C#.

Referências:


José Carlos Macoratti