Pular para o conteúdo
.NETInit-only, required e target-typed new
Módulo 01Fundamentos da Plataforma e da Linguagem

Init-only, required e target-typed new

intermediario 25 min de leitura·Atualizado · .NET 9
Resumo

init permite definir uma propriedade só na criação; required obriga o chamador a informá-la; target-typed new() remove a repetição do nome do tipo. Juntos, tornam a inicialização segura e concisa.

1. Objetivos de Aprendizagem#

  • Usar propriedades init para imutabilidade após a criação.
  • Obrigar propriedades essenciais com required.
  • Simplificar instâncias com target-typed new().

2. Pré-requisitos#

  • Records e imutabilidade (tópico 6.1).

3. Conceito#

  • init: o setter só pode ser usado durante a inicialização (construtor ou object initializer). Depois, a propriedade é somente-leitura.
  • required: o compilador exige que a propriedade seja definida na criação, sem precisar de um construtor completo.
  • Target-typed new(): quando o tipo já é conhecido pelo contexto (variável, parâmetro), você escreve só new().

O porquê: garantir que objetos nasçam completos e imutáveis, com menos código repetitivo.

4. Mão na Massa#

4.1. Setup#

Shell
dotnet new console -n Catalog.Init
cd Catalog.Init

4.2. Implementação Passo a Passo#

  1. init + required:
C#
public class Produto
{
    public required string Nome { get; init; }
    public required decimal Preco { get; init; }
    public string? Descricao { get; init; }   // opcional
}

var p = new Produto { Nome = "Teclado", Preco = 120m };
// p.Nome = "x";  // ERRO: init-only, não pode alterar depois

Omitir Nome ou Preco acima gera erro de compilação (por causa de required).

  1. Target-typed new():
C#
Produto criar() => new() { Nome = "Mouse", Preco = 90m };

List<int> numeros = new() { 1, 2, 3 };  // tipo inferido do lado esquerdo

4.3. Executando#

Shell
dotnet run

5. Exemplo Completo#

C#
public class CriarProdutoRequest
{
    public required string Nome { get; init; }
    public required decimal Preco { get; init; }
}

CriarProdutoRequest req = new() { Nome = "Monitor", Preco = 1200m };

O DTO é imutável, obriga os campos essenciais e é criado sem repetir o nome do tipo.

6. Boas Práticas e Armadilhas#

FaçaEvite
Marcar campos obrigatórios como requiredDeixar objetos nascerem incompletos e validar tarde
Usar init para imutabilidade pós-criaçãoset público quando o valor não deveria mudar
Target-typed new() quando o tipo é óbvioAbusar de new() onde o tipo fica ilegível
Atenção

required é verificado em compilação ao usar object initializer. Frameworks que criam objetos por reflexão (serializadores) têm suporte específico — configure-os quando necessário.

7. Segurança e Produção#

  • required + init garantem invariantes na criação, reduzindo estados inválidos que só apareceriam em runtime.

8. Exercícios#

  • Fácil: crie um DTO com duas propriedades required.
  • Médio: tente criar o objeto sem uma delas e observe o erro do compilador.
  • Desafio: combine required, init e target-typed new() num pequeno modelo de pedido.

9. Resumo#

init dá imutabilidade após a criação; required obriga campos essenciais; target-typed new() remove repetição. Juntos, produzem inicialização segura e concisa.

10. Próximos Passos#

Encerramos C# moderno. A seguir, estruturas de dados: coleções e generics.

11. Referências#

06-03 — Init-only, required e target-typed new | Curso ASP.NET Core