Membri Obligatorii și Inițializare Sigură în C#: Modificatorii required și init în C# (.NET)

Ghid complet pentru inițializarea sigură a obiectelor în C#: utilizarea cuvântului cheie required pentru a impune setarea proprietăților la instanțiere, imutabilitate cu init-only setters și atributul SetsRequiredMembers.

Sintaxă C#
public required string Email { get; init; } | [SetsRequiredMembers]

Înainte de C# 11, dezvoltatorii erau prinși într-o dilemă arhitecturală clasică: pentru a garanta că un obiect nu este creat cu proprietăți esențiale nule (ex: Email sau Id), trebuiau să scrie constructori telescopici greoi cu zeci de parametri, pierzând eleganța inițializatorilor de obiecte new User { Email = "..." }.

Modificatorul required rezolvă definitiv această problemă: el forțează apelantul să atribuie o valoare proprietății în momentul instanțierii, în timp ce accesorul init garantează că proprietatea nu mai poate fi modificată ulterior (imutabilitate completă).

Definirea DTO-urilor Sigure cu required și init
public class UtilizatorDto
{
    // Câmp obligatoriu: compilatorul dă eroare dacă nu este furnizat la new!
    public required string NumeUtilizator { get; init; }
    public required string Email { get; init; }

    // Câmp opțional cu valoare implicită:
    public string Rol { get; init; } = "Utilizator";
}

public class Program
{
    public static void Main()
    {
        // 1. Instanțiere validă:
        var u1 = new UtilizatorDto
        {
            NumeUtilizator = "Dexter",
            Email = "contact@dexblog.ro"
        };

        // 2. Imutabilitate garantată:
        // u1.Email = "alt@email.ro"; // EROARE DE COMPILARE: 'init' permite atribuire doar la creare!

        // 3. Eșec la compilare dacă lipsește un membru obligatoriu:
        // var u2 = new UtilizatorDto { NumeUtilizator = "Incomplet" }; 
        // EROARE: Required member 'UtilizatorDto.Email' must be set in object initializer!
    }
}

Atributul [SetsRequiredMembers] pentru Constructori

Dacă doriți să oferiți și un constructor clasic care populează manual câmpurile obligatorii, decorați-l cu [SetsRequiredMembers] pentru a semnala compilatorului că regulile au fost respectate:

public class Client
{
    public required string Cif { get; init; }

    [SetsRequiredMembers]
    public Client(string cif)
    {
        this.Cif = cif;
    }

    public Client() {} // Permite și inițializator de obiecte
}