0Pricing
C# Academy · Lezione

Abilitazione e comprensione di NRT

Abiliti il contesto nullable, comprenda i tipi reference nullable e non-nullable e interpreti gli avvisi del compilatore.

Abilitazione e comprensione di NRT è una lezione C# Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento C# Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso C# Academy include 4 lezioni in totale.

L'errore da un miliardo di dollari

Tony Hoare (l'inventore di null) lo definì il suo «errore da un miliardo di dollari». In C#, qualsiasi tipo riferimento poteva essere null per impostazione predefinita, rendendo NullReferenceException l'errore di runtime più comune. I Nullable Reference Types (NRT) risolvono il problema a livello di compilatore.

Abilitazione del contesto nullable

Abiliti gli NRT a livello globale nel file di progetto oppure per singolo file tramite direttive. Una volta abilitati, il compilatore considera i tipi riferimento non nullable per impostazione predefinita.

<!-- In .csproj — enable for the whole project -->
<PropertyGroup>
  <Nullable>enable</Nullable>
</PropertyGroup>

// Or per-file:
#nullable enable
// ... code with NRT warnings
#nullable disable
// ... code without NRT warnings

Tipi riferimento non nullable e nullable

Con gli NRT abilitati: string significa che il valore è mai null, mentre string? significa che potrebbe essere null. Il compilatore emette un avviso se assegna null a un tipo non nullable o se dereferenzia un tipo nullable senza un controllo.

#nullable enable

string nonNull = "Hello";    // OK
string? maybeNull = null;    // OK — explicitly nullable

nonNull = null;              // WARNING: CS8600
Console.WriteLine(maybeNull.Length); // WARNING: CS8602 — may be null

// Fix:
if (maybeNull is not null)
    Console.WriteLine(maybeNull.Length); // safe

Analisi del flusso

Il compilatore esegue l'analisi del flusso: tiene traccia dello stato null attraverso condizioni e rami, eliminando gli avvisi quando può dimostrare che un valore non è null.

string? name = GetName();

// After null check, name is treated as non-null:
if (name is not null)
    Console.WriteLine(name.Length);  // no warning

// Same with early return:
if (name is null) return;
Console.WriteLine(name.Length);     // no warning — null was returned

// Pattern matching:
if (name is string s)
    Console.WriteLine(s.ToUpper()); // no warning

Avvisi nullable: CS8600–CS8629

È importante comprendere questi avvisi NRT: CS8600 (assegnazione di null a un tipo non nullable), CS8602 (dereferenziazione di un valore che potrebbe essere null), CS8603 (restituzione di null per un tipo non nullable), CS8618 (campo non nullable non inizializzato).

#nullable enable

public class Order
{
    public string CustomerName { get; set; } // CS8618: not initialized
    public string? TrackingNumber { get; set; } // OK — nullable

    public Order(string name)
    {
        CustomerName = name; // now initialized — CS8618 gone
    }
}

string? s = GetValue();
Console.WriteLine(s.Length); // CS8602: s might be null

Inizializzazione dei campi non nullable

CS8618 viene generato quando un campo o una proprietà non nullable non viene impostata nel costruttore. Le soluzioni sono inizializzarla nella dichiarazione, renderla obbligatoria tramite il costruttore oppure utilizzare l'operatore null-forgiving per i pattern DI/ORM.

// Option 1: Initialize in declaration
public string Name { get; set; } = "";

// Option 2: Require via constructor
public class Product
{
    public string Name { get; }
    public Product(string name) => Name = name;
}

// Option 3: null-forgiving for ORM entities
public string Name { get; set; } = null!;
// null! tells compiler "trust me, this will be set by EF Core"

Nullable nei tipi generici

I parametri di tipo generici possono essere vincolati a valori non nullable. Un vincolo where T : notnull garantisce che T non possa mai essere null.

// Without constraint: T could be nullable
public T? Find<T>(int id) { ... }

// With notnull: T must be a non-nullable type
public T FindRequired<T>(int id) where T : notnull
{
    var result = InternalFind<T>(id);
    return result ?? throw new KeyNotFoundException();
}

// T? is meaningful only when T is known to be non-nullable
public T? FindOrDefault<T>(int id) where T : class { ... }

Nullable nelle interfacce e negli override

Quando implementa un'interfaccia o esegue l'override di un metodo, le annotazioni di nullabilità devono corrispondere. Il compilatore verifica che le implementazioni siano almeno altrettanto non nullable di quanto dichiarato dall'interfaccia.

public interface IRepository<T>
{
    T? FindById(int id);       // may return null
    T GetOrThrow(int id);      // never null
}

// Implementation:
public class ProductRepo : IRepository<Product>
{
    public Product? FindById(int id)  => _db.Find(id);
    public Product  GetOrThrow(int id) =>
        _db.Find(id) ?? throw new KeyNotFoundException();
}

Tipi valore nullable e tipi riferimento nullable

Non confonda int? (Nullable<int>, un wrapper per tipi valore esistente prima di C# 8) con string? (un'annotazione NRT valida solo in fase di compilazione, senza overhead di runtime).

// Nullable value type (runtime Nullable<int>)
int? age = null;
bool hasValue = age.HasValue;
int value  = age.GetValueOrDefault();

// Nullable reference type (compile-time annotation only)
string? name = null;
// string? has NO runtime wrapper — it's just a compile-time hint
// null check is still needed at runtime
if (name is not null)
    Console.WriteLine(name.ToUpper());

Soppressione degli avvisi con !

L'operatore null-forgiving (!) sopprime uno specifico avviso di nullabilità quando Lei sa più del compilatore. Lo utilizzi con moderazione e documenti il motivo per cui è sicuro.

// Use ! when you know the value cannot be null
var user = _db.Users.FirstOrDefault(u => u.Email == email);
var name = user!.Name; // user is guaranteed by business logic

// EF Core navigation properties set by the framework:
public class Order
{
    public Customer Customer { get; set; } = null!; // set by EF Core
}

Caso reale: risposta API nullable

Un wrapper API in cui alcuni campi possono essere presenti o meno nella risposta JSON: le annotazioni nullable comunicano chiaramente l'intento.

#nullable enable

public class WeatherResponse
{
    public string City { get; set; } = "";     // always present
    public double Temperature { get; set; }     // always present
    public string? Description { get; set; }    // optional field
    public string? AlertMessage { get; set; }   // only when there's an alert
}

// Consumer:
var weather = await api.GetWeatherAsync("London");
Console.WriteLine(weather.City);            // safe
Console.WriteLine(weather.Description?.ToUpper() ?? "N/A"); // safe null-handling

Verifica rapida

Qual è l'overhead di runtime dei Nullable Reference Types (string?) rispetto ai normali tipi riferimento (string)?

Riepilogo: abilitazione e comprensione degli NRT

Punti chiave:

  • Abiliti globalmente con <Nullable>enable</Nullable> nel file .csproj
  • string = mai null; string? = può essere null
  • L'analisi del flusso tiene traccia dello stato null attraverso rami e valori restituiti
  • Le annotazioni NRT valgono solo in fase di compilazione: nessun overhead di runtime
  • CS8618: inizializzi i campi non nullable nel costruttore o utilizzi = null! per gli ORM
  • Utilizzi ! con moderazione e documenti perché il null-forgiving è sicuro

Domande Frequenti

La lezione «Abilitazione e comprensione di NRT» è gratuita?

Sì — il testo completo di «Abilitazione e comprensione di NRT» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso C# Academy, passa a CoddyKit PRO. Il corso C# Academy include 4 lezioni in totale.

Cosa imparerò in «Abilitazione e comprensione di NRT»?

Abiliti il contesto nullable, comprenda i tipi reference nullable e non-nullable e interpreti gli avvisi del compilatore. Eserciti C# Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare C# Academy?

Non è richiesta alcuna esperienza precedente. C# Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.

Quanto tempo richiede la lezione «Abilitazione e comprensione di NRT»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione C# Academy?

Sì. Ogni lezione C# Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Abilitazione e comprensione di NRT
  2. Annotazioni: ?, !, MaybeNull e NotNull
  3. Operatori null-conditional e null-coalescing
  4. Migrazione di una codebase a NRT
← Torna a C# Academy