Condividi tramite


Modificatore obbligatorio (Riferimento a C#)

Il modificatore required indica che il campo o la proprietà a cui è applicato deve essere inizializzato da un inizializzatore di oggetto . Qualsiasi espressione che inizializza una nuova istanza del tipo deve inizializzare tutti i membri necessari . Il modificatore required è disponibile a partire da C# 11. Il modificatore required consente agli sviluppatori di creare tipi in cui le proprietà o i campi devono essere inizializzati correttamente, ma consentono comunque l'inizializzazione usando gli inizializzatori di oggetto. Alcune regole assicurano questo comportamento:

  • Il modificatore required può essere applicato ai campi e proprietà dichiarate nei tipi structe class, inclusi i tipi record e record struct. Il modificatore required non può essere applicato ai membri di un interface.
  • Le implementazioni esplicite dell'interfaccia non possono essere contrassegnate come required. Non possono essere impostati negli inizializzatori di oggetti.
  • I membri obbligatori devono essere inizializzati, ma possono essere inizializzati per null. Se il tipo è un tipo riferimento non nullabile, il compilatore genera un avviso se si inizializza il membro a null. Il compilatore genera un errore se il membro non viene inizializzato affatto.
  • I membri obbligatori devono essere almeno tanto visibili quanto il loro tipo contenitore. Ad esempio, una classe public non può contenere un campo requiredprotected. Inoltre, le proprietà obbligatorie devono avere setter (accessorset o init) che sono almeno altrettanto visibili quanto i tipi che li contengono. I membri che non sono accessibili non possono essere impostati dal codice che crea un'istanza.
  • Le classi derivate non possono nascondere un membro required dichiarato nella classe base. Nascondere un membro richiesto impedisce ai chiamanti di usare gli inizializzatori di oggetto per esso. Inoltre, i tipi derivati che eseguono l'override di una proprietà obbligatoria devono includere il modificatore required. Il tipo derivato non può rimuovere lo stato required. I tipi derivati possono aggiungere il modificatore required quando si esegue l'override di una proprietà.
  • Un tipo con qualsiasi membro required non può essere utilizzato come argomento di tipo quando il parametro di tipo include il vincolo new(). Il compilatore non può imporre che tutti i membri necessari vengano inizializzati nel codice generico.
  • Il modificatore required non è consentito nella dichiarazione per i parametri posizionali in un record. È possibile aggiungere una dichiarazione esplicita per una proprietà posizionale che include il modificatore required.

Alcuni tipi, come i record posizionali , usano un costruttore primario per inizializzare le proprietà posizionali. Se una di queste proprietà include il modificatore required, il costruttore primario aggiunge l'attributo SetsRequiredMembers. Ciò indica che il costruttore primario inizializza tutti i membri necessari. È possibile scrivere il proprio costruttore con l'attributo System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute. Tuttavia, il compilatore non verifica che questi costruttori inizializzino tutti i membri necessari. Invece, l'attributo asserisce al compilatore che il costruttore inizializza tutti i membri necessari. L'attributo SetsRequiredMembers aggiunge queste regole ai costruttori:

  • Un costruttore concatenato a un altro costruttore annotato con l'attributo SetsRequiredMembers, this()o base(), deve includere anche l'attributo SetsRequiredMembers. Ciò garantisce che i chiamanti possano usare correttamente tutti i costruttori appropriati.
  • I costruttori di copia generati per i tipi record hanno l'attributo SetsRequiredMembers applicato se uno dei membri è required.

Avvertimento

Il SetsRequiredMembers disabilita i controlli del compilatore affinché tutti i membri required vengano inizializzati quando viene creato un oggetto. Usarlo con cautela.

Il codice seguente mostra una gerarchia di classi che usa il modificatore required per le proprietà FirstName e LastName:

public class Person
{
    public Person() { }

    [SetsRequiredMembers]
    public Person(string firstName, string lastName) =>
        (FirstName, LastName) = (firstName, lastName);

    public required string FirstName { get; init; }
    public required string LastName { get; init; }

    public int? Age { get; set; }
}

public class Student : Person
{
    public Student() : base()
    {
    }

    [SetsRequiredMembers]
    public Student(string firstName, string lastName) :
        base(firstName, lastName)
    {
    }

    public double GPA { get; set; }
}

Per altre informazioni sui membri necessari, vedere C#11 - Membri obbligatori specifica della funzionalità.