Î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ă).
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
}