Tipi riferimento nullable

Prima di C# 8.0, tutti i tipi riferimento erano nullable. I tipi riferimento nullable fanno riferimento a un gruppo di funzionalità introdotte in C# 8.0 che è possibile usare per ridurre al minimo la probabilità che il codice generi la generazione System.NullReferenceExceptiondel runtime. I tipi riferimento nullable includono tre funzionalità che consentono di evitare queste eccezioni, inclusa la possibilità di contrassegnare in modo esplicito un tipo riferimento come nullable:

  • Analisi dei flussi statici migliorata che determina se una variabile può essere null prima di dereferenziarla.
  • Attributi che annotano le API in modo che l'analisi del flusso determini lo stato Null.
  • Annotazioni variabili usate dagli sviluppatori per dichiarare in modo esplicito lo stato Null previsto per una variabile.

L'analisi dello stato Null e le annotazioni delle variabili sono disabilitate per impostazione predefinita per i progetti esistenti, vale a dire che tutti i tipi di riferimento continuano a essere nullable. A partire da .NET 6, sono abilitati per impostazione predefinita per i nuovi progetti. Per informazioni sull'abilitazione di queste funzionalità dichiarando un contesto di annotazione nullable, vedere Contesti nullable.

Il resto di questo articolo descrive il funzionamento di queste tre aree di funzionalità per generare avvisi quando il codice potrebbe dereferenziare un null valore. Dereferenziare una variabile significa accedere a uno dei relativi membri usando l'operatore . (punto), come illustrato nell'esempio seguente:

string message = "Hello, World!";
int length = message.Length; // dereferencing "message"

Quando si dereferenzia una variabile il cui valore è null, il runtime genera un'eccezione System.NullReferenceException.

È anche possibile esplorare questi concetti nel modulo learn sulla sicurezza nullable in C#.

Analisi dello stato Null

L'analisi dello stato Null tiene traccia dello stato Null dei riferimenti. Questa analisi statica genera avvisi quando il codice può dereferenziare null. È possibile risolvere questi avvisi per ridurre al minimo le incidenze quando il runtime genera un oggetto System.NullReferenceException. Il compilatore usa l'analisi statica per determinare lo stato Null di una variabile. Una variabile è not-null o forse-null. Il compilatore determina che una variabile non è Null in due modi:

  1. Alla variabile è stato assegnato un valore noto come non Null.
  2. La variabile è stata verificata null in base a e non è stata modificata dopo tale controllo.

Qualsiasi variabile che il compilatore non ha determinato come not-null viene considerata forse-null. L'analisi fornisce avvisi in situazioni in cui è possibile dereferenziare accidentalmente un null valore. Il compilatore genera avvisi in base allo stato Null.

  • Quando una variabile non è Null, tale variabile può essere dereferenziata in modo sicuro.
  • Quando una variabile è forse Null, tale variabile deve essere controllata per assicurarsi che non null sia prima di dereferenziarla.

Si consideri l'esempio seguente:

string message = null;

// warning: dereference null.
Console.WriteLine($"The length of the message is {message.Length}");

var originalMessage = message;
message = "Hello, World!";

// No warning. Analysis determined "message" is not null.
Console.WriteLine($"The length of the message is {message.Length}");

// warning!
Console.WriteLine(originalMessage.Length);

Nell'esempio precedente il compilatore determina che message è forse Null quando viene stampato il primo messaggio. Non viene visualizzato alcun avviso per il secondo messaggio. La riga finale del codice genera un avviso perché originalMessage potrebbe essere Null. L'esempio seguente illustra un uso più pratico per attraversare un albero di nodi alla radice, elaborando ogni nodo durante l'attraversamento:

void FindRoot(Node node, Action<Node> processNode)
{
    for (var current = node; current != null; current = current.Parent)
    {
        processNode(current);
    }
}

Il codice precedente non genera avvisi per dereferenziare la variabile current. L'analisi statica determina che current non viene mai dereferenziata quando è forse Null. La variabile current viene verificata null prima current.Parent dell'accesso e prima di passare current all'azione ProcessNode . Negli esempi precedenti viene illustrato come il compilatore determina lo stato Null per le variabili locali durante l'inizializzazione, l'assegnazione o il confronto con null.

L'analisi dello stato Null non viene tracciata nei metodi chiamati. Di conseguenza, i campi inizializzati in un metodo helper comune chiamato dai costruttori genereranno un avviso con il modello seguente:

La proprietà 'name' non nullable deve contenere un valore non Null quando si esce dal costruttore.

È possibile risolvere questi avvisi in uno dei due modi seguenti: concatenamento del costruttore o attributi nullable nel metodo helper. Il codice seguente visualizza un esempio con ogni metodo. La Person classe usa un costruttore comune chiamato da tutti gli altri costruttori. La Student classe ha un metodo helper annotato con l'attributo System.Diagnostics.CodeAnalysis.MemberNotNullAttribute :


using System.Diagnostics.CodeAnalysis;

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }

    public Person() : this("John", "Doe") { }
}

public class Student : Person
{
    public string Major { get; set; }

    public Student(string firstName, string lastName, string major)
        : base(firstName, lastName)
    {
        SetMajor(major);
    }

    public Student(string firstName, string lastName) :
        base(firstName, lastName)
    {
        SetMajor();
    }

    public Student()
    {
        SetMajor();
    }

    [MemberNotNull(nameof(Major))]
    private void SetMajor(string? major = default)
    {
        Major = major ?? "Undeclared";
    }
}

Nota

Sono stati aggiunti alcuni miglioramenti all'assegnazione definita e all'analisi dello stato Null in C# 10. Quando si esegue l'aggiornamento a C# 10, è possibile che vengano visualizzati meno avvisi nullable che sono falsi positivi. Altre informazioni sui miglioramenti apportati alla specifica delle funzionalità per i miglioramenti delle assegnazioni definite.

L'analisi dello stato nullable e gli avvisi generati dal compilatore consentono di evitare errori del programma dereferenziando null. L'articolo sulla risoluzione degli avvisi nullable fornisce tecniche per correggere gli avvisi che probabilmente verranno visualizzati nel codice.

Attributi nelle firme API

L'analisi dello stato Null richiede hint da parte degli sviluppatori per comprendere la semantica delle API. Alcune API forniscono controlli Null e devono modificare lo stato Null di una variabile da maybe-null a not-null. Altre API restituiscono espressioni che non sono Null o forse Null a seconda dello stato Null degli argomenti di input. Si consideri ad esempio il codice seguente che visualizza un messaggio:

public void PrintMessage(string message)
{
    if (!string.IsNullOrWhiteSpace(message))
    {
        Console.WriteLine($"{DateTime.Now}: {message}");
    }
}

In base all'ispezione, qualsiasi sviluppatore considererebbe questo codice sicuro e non dovrebbe generare avvisi. Il compilatore non sa che IsNullOrWhiteSpace fornisce un controllo Null. Si applicano attributi per informare il compilatore che messagenon è Null se e solo se IsNullOrWhiteSpace restituisce false. Nell'esempio precedente la firma include per NotNullWhen indicare lo stato Null di message:

public static bool IsNullOrWhiteSpace([NotNullWhen(false)] string message);

Gli attributi forniscono informazioni dettagliate sullo stato Null degli argomenti, dei valori restituiti e dei membri dell'istanza dell'oggetto utilizzata per richiamare un membro. I dettagli su ogni attributo sono disponibili nell'articolo di riferimento sul linguaggio sugli attributi di riferimento nullable. Tutte le API di runtime .NET sono state annotate in .NET 5. È possibile migliorare l'analisi statica annotando le API per fornire informazioni semantiche sullo stato Null degli argomenti e sui valori restituiti.

Annotazioni variabili nullable

L'analisi dello stato Null offre un'analisi affidabile per la maggior parte delle variabili. Il compilatore necessita di altre informazioni per le variabili membro. Il compilatore non può fare ipotesi sull'ordine in cui si accede ai membri pubblici. È possibile accedere a qualsiasi membro pubblico in qualsiasi ordine. È possibile utilizzare uno dei costruttori accessibili per inizializzare l'oggetto. Se un campo membro potrebbe essere nullimpostato su , il compilatore deve presupporre che lo stato Null sia forse Null all'inizio di ogni metodo.

Si usano annotazioni che possono dichiarare se una variabile è un tipo riferimento nullable o un tipo riferimento non nullable. Queste annotazioni apportano istruzioni importanti sullo stato Null per le variabili:

  • Un riferimento non deve essere Null. Lo stato predefinito di una variabile di riferimento non nullable è diverso da Null. Il compilatore applica regole che assicurano che sia sicuro dereferenziare queste variabili senza prima verificare che non sia Null:
    • La variabile deve essere inizializzata come valore non Null.
    • Alla variabile non può mai essere assegnato il valore null. Il compilatore genera un avviso quando il codice assegna un'espressione forse Null a una variabile che non deve essere Null.
  • Un riferimento potrebbe essere Null. Lo stato predefinito di una variabile di riferimento nullable è forse Null. Il compilatore applica le regole per assicurarsi di aver verificato correttamente la presenza di un null riferimento:
    • La variabile può essere dereferenziata solo quando il compilatore può garantire che il valore non nullsia .
    • Queste variabili possono essere inizializzate con il valore predefinito null e possono ricevere l'assegnazione del valore null in un altro codice.
    • Il compilatore non genera avvisi quando il codice assegna un'espressione forse Null a una variabile che può essere Null.

Qualsiasi variabile di riferimento che non deve essere null con stato Null non null. Qualsiasi variabile di riferimento che inizialmente può avere null lo stato Null di maybe-null.

Viene inserita una nota in un tipo riferimento nullable usando la stessa sintassi dei tipi valore nullable: viene aggiunto ? al tipo della variabile. La dichiarazione della variabile seguente, ad esempio, rappresenta una variabile di stringa nullable, name:

string? name;

Qualsiasi variabile in cui ? non viene aggiunto al nome del tipo è un tipo riferimento non nullable. Che include tutte le variabili di tipo riferimento nel codice esistente quando è stata abilitata questa funzionalità. Tuttavia, tutte le variabili locali tipizzate in modo implicito (dichiarate usando var) sono tipi riferimento nullable. Come illustrato nelle sezioni precedenti, l'analisi statica determina lo stato Null delle variabili locali per determinare se sono forse Null.

A volte è necessario eseguire l'override di un avviso quando si sa che una variabile non è Null, ma il compilatore determina che lo stato null è forse Null. Si usa l'operatore !null-forgiving seguendo un nome di variabile per forzare lo stato Null in modo che non sia Null. Ad esempio, se si sa che la name variabile non null è ma il compilatore genera un avviso, è possibile scrivere il codice seguente per eseguire l'override dell'analisi del compilatore:

name!.Length;

I tipi riferimento nullable e i tipi valore nullable forniscono un concetto semantico simile: una variabile può rappresentare un valore o un oggetto o tale variabile può essere null. Tuttavia, i tipi riferimento nullable e i tipi valore nullable vengono implementati in modo diverso: i tipi valore nullable vengono implementati usando System.Nullable<T>e i tipi riferimento nullable vengono implementati dagli attributi letti dal compilatore. Ad esempio, string? e string sono entrambi rappresentati dallo stesso tipo: System.String. Tuttavia, int? e int sono rappresentati rispettivamente da System.Nullable<System.Int32> e System.Int32.

I tipi riferimento nullable sono una funzionalità in fase di compilazione. Ciò significa che è possibile che i chiamanti ignorino gli avvisi, usare null intenzionalmente come argomento per un metodo che prevede un riferimento non nullable. Gli autori della libreria devono includere controlli di runtime rispetto ai valori degli argomenti Null. È ArgumentNullException.ThrowIfNull l'opzione preferita per controllare un parametro su Null in fase di esecuzione.

Importante

L'abilitazione di annotazioni nullable può modificare il modo in cui Entity Framework Core determina se è necessario un membro dati. Per altre informazioni, vedere l'articolo Concetti fondamentali di Entity Framework Core: Uso dei tipi riferimento nullable.

Generics

I generics richiedono regole dettagliate per gestire T? per qualsiasi parametro Tdi tipo . Le regole sono necessariamente dettagliate a causa della cronologia e dell'implementazione diversa per un tipo valore nullable e un tipo riferimento nullable. I tipi valore nullable vengono implementati usando lo System.Nullable<T> struct . I tipi riferimento nullable vengono implementati come annotazioni di tipo che forniscono regole semantiche al compilatore.

In C# 8.0, l'uso T? senza vincolare T per essere o struct non class è stato compilato. Ciò ha consentito al compilatore di interpretare T? in modo chiaro. Tale restrizione è stata rimossa in C# 9.0, definendo le regole seguenti per un parametro di tipo non vincolato T:

  • Se l'argomento di tipo per T è un tipo riferimento, T? fa riferimento al tipo riferimento nullable corrispondente. Ad esempio, se T è un stringoggetto , è T? .string?
  • Se l'argomento di tipo per T è un tipo valore, T? fa riferimento allo stesso tipo di valore, T. Ad esempio, se T è un intoggetto , T? è anche un oggetto int.
  • Se l'argomento di tipo per T è un tipo riferimento nullable, T? fa riferimento allo stesso tipo riferimento nullable. Ad esempio, se T è un string?oggetto , T? è anche un oggetto string?.
  • Se l'argomento di tipo per T è un tipo valore nullable, T? fa riferimento allo stesso tipo di valore nullable. Ad esempio, se T è un int?oggetto , T? è anche un oggetto int?.

Per i valori restituiti, T? equivale a . Per i valori degli [MaybeNull]Targomenti, T? equivale a [AllowNull]T. Per altre informazioni, vedere l'articolo attributi per l'analisi dello stato Null nel riferimento al linguaggio.

È possibile specificare un comportamento diverso usando vincoli:

  • Il class vincolo indica che T deve essere un tipo riferimento non nullable , ad esempio string. Il compilatore genera un avviso se si usa un tipo riferimento nullable, ad esempio string? per T.
  • Il class? vincolo indica che T deve essere un tipo riferimento, non nullable (string) o un tipo riferimento nullable (ad esempio string?). Quando il parametro di tipo è un tipo riferimento nullable, ad esempio string?, un'espressione di T? riferimenti dello stesso tipo riferimento nullable, ad esempio string?.
  • Il notnull vincolo significa che T deve essere un tipo riferimento non nullable o un tipo valore non nullable. Se si usa un tipo riferimento nullable o un tipo valore nullable per il parametro di tipo, il compilatore genera un avviso. Inoltre, quando T è un tipo valore, il valore restituito è tale tipo di valore, non il tipo di valore nullable corrispondente.

Questi vincoli consentono di fornire altre informazioni al compilatore su come T verrà usato. Ciò consente agli sviluppatori di scegliere il tipo per Te offre un'analisi dello stato Null migliore quando viene usata un'istanza del tipo generico.

Contesti nullable

Le nuove funzionalità che proteggono dalla generazione di un'eccezione System.NullReferenceException possono essere dirompenti quando sono attivate in una codebase esistente:

  • Tutte le variabili di riferimento tipizzate in modo esplicito vengono interpretate come tipi riferimento non nullable.
  • Il significato del class vincolo nei generics è stato modificato in modo da significare un tipo riferimento non nullable.
  • I nuovi avvisi vengono generati a causa di queste nuove regole.

È necessario acconsentire esplicitamente all'uso di queste funzionalità nei progetti esistenti. Che fornisce un percorso di migrazione e mantiene la compatibilità con le versioni precedenti. I contesti nullable consentono il controllo con granularità fine di come il compilatore interpreta le variabili dei tipi riferimento. Il contesto di annotazione nullable determina il comportamento del compilatore. Esistono quattro valori per il contesto di annotazione nullable:

  • disable: il compilatore si comporta in modo analogo a C# 7.3 e versioni precedenti:
    • Gli avvisi nullable sono disabilitati.
    • Tutte le variabili di tipo riferimento sono tipi riferimento nullable.
    • Non è possibile dichiarare una variabile come tipo riferimento nullable usando il ? suffisso sul tipo.
    • È possibile usare l'operatore di forgiving Null, !, ma non ha alcun effetto.
  • enable: il compilatore abilita l'analisi dei riferimenti Null e tutte le funzionalità del linguaggio.
    • Tutti i nuovi avvisi nullable sono abilitati.
    • È possibile usare il ? suffisso per dichiarare un tipo riferimento nullable.
    • Tutte le altre variabili di tipo riferimento sono tipi riferimento non nullable.
    • L'operatore di forgiving Null elimina gli avvisi per un'assegnazione possibile a null.
  • avvisi: il compilatore esegue tutte le analisi Null e genera avvisi quando il codice potrebbe dereferenziare null.
    • Tutti i nuovi avvisi nullable sono abilitati.
    • L'uso del ? suffisso per dichiarare un tipo riferimento nullable genera un avviso.
    • Tutte le variabili di tipo riferimento possono essere Null. Tuttavia, i membri hanno lo stato Null di not-null alla parentesi graffa di apertura di tutti i metodi, a meno che non sia dichiarato con il ? suffisso .
    • È possibile usare l'operatore di forgiving Null, !.
  • annotazioni: il compilatore non esegue l'analisi Null o genera avvisi quando il codice potrebbe dereferenziare null.
    • Tutti i nuovi avvisi nullable sono disabilitati.
    • È possibile usare il ? suffisso per dichiarare un tipo riferimento nullable.
    • Tutte le altre variabili di tipo riferimento sono tipi riferimento non nullable.
    • È possibile usare l'operatore di forgiving Null, !, ma non ha alcun effetto.

Il contesto di annotazione nullable e il contesto di avviso nullable possono essere impostati per un progetto usando l'elemento<Nullable> nel file con estensione csproj. Questo elemento configura il modo in cui il compilatore interpreta i valori Null dei tipi e gli avvisi generati. La tabella seguente illustra i valori consentiti e riepiloga i contesti specificati.

Contesto Avvisi di dereferenziazione Avvisi di assegnazione Tipi riferimento ? Suffisso ! Operatore
disable Disabled Disabled Tutti sono nullable Non è possibile usare Non ha alcun effetto
enable Attivato Attivato Non nullable a meno che non sia dichiarato con ? Dichiara il tipo nullable Elimina gli avvisi per l'assegnazione possibile null
warnings Attivato Non applicabile Tutti sono nullable, ma i membri vengono considerati non Null alla parentesi graffa di apertura dei metodi Genera un avviso Elimina gli avvisi per l'assegnazione possibile null
annotations Disabled Disabled Non nullable a meno che non sia dichiarato con ? Dichiara il tipo nullable Non ha alcun effetto

Le variabili di tipo riferimento nel codice compilato prima di C# 8 o in un contesto disabilitato sono oblivious. È possibile assegnare un null valore letterale o una variabile forse Null a una variabile che è oblivious nullable. Tuttavia, lo stato predefinito di una variabile nullable-obliviousnon è Null.

È possibile scegliere quale impostazione è migliore per il progetto:

  • Scegliere disabilita per i progetti legacy che non si desidera aggiornare in base alla diagnostica o alle nuove funzionalità.
  • Scegliere avvisi per determinare dove può generare System.NullReferenceExceptionil codice. È possibile risolvere tali avvisi prima di modificare il codice per abilitare tipi di riferimento non nullable.
  • Scegliere annotazioni per esprimere la finalità di progettazione prima di abilitare gli avvisi.
  • Scegliere abilita per nuovi progetti e progetti attivi in cui si desidera proteggere da eccezioni di riferimento Null.

Esempio:

<Nullable>enable</Nullable>

È anche possibile usare le direttive per impostare questi stessi contesti ovunque nel codice sorgente. Questi sono più utili quando si esegue la migrazione di una codebase di grandi dimensioni.

  • #nullable enable: imposta il contesto di annotazione nullable e il contesto di avviso nullable per abilitare.
  • #nullable disable: imposta il contesto di annotazione nullable e il contesto di avviso nullable per disabilitare.
  • #nullable restore: ripristina il contesto di annotazione nullable e il contesto di avviso nullable alle impostazioni del progetto.
  • #nullable disable warnings: impostare il contesto di avviso nullable per disabilitare.
  • #nullable enable warnings: impostare il contesto di avviso nullable per abilitare.
  • #nullable restore warnings: ripristina il contesto di avviso nullable nelle impostazioni del progetto.
  • #nullable disable annotations: impostare il contesto di annotazione nullable per disabilitare.
  • #nullable enable annotations: impostare il contesto di annotazione nullable per abilitare.
  • #nullable restore annotations: ripristina il contesto di avviso di annotazione nelle impostazioni del progetto.

Per qualsiasi riga di codice, è possibile impostare una delle combinazioni seguenti:

Contesto di avviso Contesto di annotazione Uso
impostazione predefinita del progetto impostazione predefinita del progetto Predefinito
abilitare disabilitare Correzione degli avvisi di analisi
abilitare impostazione predefinita del progetto Correzione degli avvisi di analisi
impostazione predefinita del progetto abilitare Aggiungere annotazioni di tipo
abilitare abilitare Codice già migrato
disabilitare abilitare Annotare il codice prima di correggere gli avvisi
disabilitare disabilitare Aggiunta di codice legacy al progetto migrato
impostazione predefinita del progetto disabilitare Raramente
disabilitare impostazione predefinita del progetto Raramente

Queste nove combinazioni forniscono un controllo con granularità fine sulla diagnostica che il compilatore genera per il codice. È possibile abilitare altre funzionalità in qualsiasi area che si sta aggiornando, senza visualizzare avvisi aggiuntivi che non sono ancora pronti per l'indirizzo.

Importante

Il contesto nullable globale non si applica per i file di codice generati. In entrambe le strategie il contesto nullable è disabilitato per qualsiasi file di origine contrassegnato come generato. Ciò significa che le API nei file generati non vengono annotate. Esistono quattro modi in cui un file viene contrassegnato come generato:

  1. In .editorconfig specificare generated_code = true in una sezione che si applica a tale file.
  2. Inserire <auto-generated> o <auto-generated/> in un commento nella parte superiore del file. Può essere in qualsiasi riga in tale commento, ma il blocco di commento deve essere il primo elemento nel file.
  3. Avviare il nome del file con TemporaryGeneratedFile_
  4. Terminare il nome del file con .designer.cs, .generated.cs, .g.cs o .g.i.cs.

I generatori possono acconsentire esplicitamente usando la #nullable direttiva del preprocessore.

Per impostazione predefinita, le annotazioni nullable e i contesti di avviso sono disabilitati. Ciò significa che il codice esistente viene compilato senza modifiche e senza generare nuovi avvisi. A partire da .NET 6, i nuovi progetti includono l'elemento <Nullable>enable</Nullable> in tutti i modelli di progetto.

Queste opzioni forniscono due strategie distinte per aggiornare una codebase esistente per usare i tipi di riferimento nullable.

Insidie note

Le matrici e gli struct che contengono tipi di riferimenti sono noti in riferimenti nullable e l'analisi statica che determina la sicurezza Null. In entrambe le situazioni, un riferimento non nullable può essere inizializzato in null, senza generare avvisi.

Struct

Uno struct che contiene tipi di riferimento non nullable consente di assegnarlo default senza avvisi. Si consideri l'esempio seguente:

using System;

#nullable enable

public struct Student
{
    public string FirstName;
    public string? MiddleName;
    public string LastName;
}

public static class Program
{
    public static void PrintStudent(Student student)
    {
        Console.WriteLine($"First name: {student.FirstName.ToUpper()}");
        Console.WriteLine($"Middle name: {student.MiddleName?.ToUpper()}");
        Console.WriteLine($"Last name: {student.LastName.ToUpper()}");
    }

    public static void Main() => PrintStudent(default);
}

Nell'esempio precedente non è presente PrintStudent(default) alcun avviso mentre i tipi di FirstName riferimento non nullable e LastName sono Null.

Un altro caso più comune è quando si gestiscono gli struct generici. Si consideri l'esempio seguente:

#nullable enable

public struct Foo<T>
{
    public T Bar { get; set; }
}

public static class Program
{
    public static void Main()
    {
        string s = default(Foo<string>).Bar;
    }
}

Nell'esempio precedente, la proprietà Bar verrà null eseguita in fase di esecuzione e viene assegnata a stringa non nullable senza avvisi.

Matrici

Le matrici sono anche un problema noto nei tipi di riferimento nullable. Si consideri l'esempio seguente che non genera avvisi:

using System;

#nullable enable

public static class Program
{
    public static void Main()
    {
        string[] values = new string[10];
        string s = values[0];
        Console.WriteLine(s.ToUpper());
    }
}

Nell'esempio precedente la dichiarazione della matrice mostra che contiene stringhe non nullable, mentre gli elementi sono tutti inizializzati in null. La variabile s viene quindi assegnata a un null valore (primo elemento della matrice). Infine, la variabile s viene dereferenziata causando un'eccezione di runtime.

Vedi anche