Condividi tramite


Istruzioni checked e unchecked (riferimento C#)

Le istruzioni checked e unchecked specificano il contesto di controllo dell'overflow per le operazioni aritmetiche e le conversioni di tipo integrale. L'istruzione predefinita è unchecked. Quando si verifica un overflow aritmetico di numeri interi, il contesto di controllo dell'overflow definisce cosa accade. In un contesto controllato viene generata una System.OverflowException; se l'overflow si verifica in un'espressione costante, avviene un errore in fase di compilazione. In un contesto non verificato, il risultato dell'operazione viene troncato rimuovendo tutti i bit di ordine elevato che non rientrano nel tipo di destinazione. Ad esempio, l'operazione di addizione esegue il wrapping dal valore massimo al valore minimo. L'esempio seguente mostra la stessa operazione in un contesto verificato e non verificato:

uint a = uint.MaxValue;

unchecked
{
    Console.WriteLine(a + 3);  // output: 2
}

try
{
    checked
    {
        Console.WriteLine(a + 3);
    }
}
catch (OverflowException e)
{
    Console.WriteLine(e.Message);  // output: Arithmetic operation resulted in an overflow.
}

Nota

Il comportamento di overflow degli operatori e delle conversioni definiti dall'utente può essere diverso da quello descritto nel paragrafo precedente. In particolare, gli operatori verificati definiti dall'utente potrebbero non generare un'eccezione in un contesto controllato.

Per maggiori informazioni, consultare le sezioni Overflow aritmetico e divisione per zero e Operatori verificati definiti dall'utente nell'articolo Operatori aritmetici.

Per specificare il contesto di controllo dell'overflow per un'espressione, è anche possibile usare gli operatori checked e unchecked, come illustrato nell'esempio seguente:

double a = double.MaxValue;

int b = unchecked((int)a);
Console.WriteLine(b);  // output: -2147483648

try
{
    b = checked((int)a);
}
catch (OverflowException e)
{
    Console.WriteLine(e.Message);  // output: Arithmetic operation resulted in an overflow.
}

Le istruzioni e gli operatori checked e unchecked influiscono solo sul contesto di controllo dell'overflow per le operazioni che sono testualmente all'interno delle parentesi del blocco di istruzioni o dell'operatore, come illustrato nell'esempio seguente:

int Multiply(int a, int b) => a * b;

int factor = 2;

try
{
    checked
    {
        Console.WriteLine(Multiply(factor, int.MaxValue));  // output: -2
    }
}
catch (OverflowException e)
{
    Console.WriteLine(e.Message);
}

try
{
    checked
    {
        Console.WriteLine(Multiply(factor, factor * int.MaxValue));
    }
}
catch (OverflowException e)
{
    Console.WriteLine(e.Message);  // output: Arithmetic operation resulted in an overflow.
}

Nell'esempio precedente, la prima chiamata della funzione locale Multiply mostra che l'istruzione checked non influisce sul contesto di controllo dell'overflow all'interno della funzione Multiply perché non viene generata alcuna eccezione. Alla seconda chiamata della funzione Multiply, l'espressione che calcola il secondo argomento della funzione viene valutata in un contesto controllato e restituisce un'eccezione mentre è testualmente all'interno del blocco dell'istruzione checked.

Il comportamento di checked e unchecked dipende dal tipo e dall'operazione. Anche per i numeri interi, le operazioni come unchecked(x / 0) sempre generano perché non esiste alcun comportamento sensato. Controllare il comportamento del tipo e dell'operazione per comprendere in che modo le parole chiave checked e unchecked influenzano il codice.

Tipi numerici e contesto di controllo dell'overflow

Le parole chiave checked e unchecked si applicano principalmente ai tipi integrali in cui c'è un comportamento logico per l'overflow. Il comportamento di wraparound, in cui T.MaxValue + 1 diventa T.MinValue, è sensato nel contesto di un valore a complemento di due. Il valore rappresentato non è corretto perché non può rientrare nello spazio di archiviazione per il tipo. Di conseguenza, i bit sono rappresentativi dei n bit inferiori del risultato completo.

Per i tipi come decimal, floatdouble, e Half che rappresentano un valore più complesso o un valore di complemento, wraparound non è ragionevole. Non può essere usato per calcolare risultati più grandi o più accurati, quindi unchecked non è utile.

float, doublee Half hanno valori di saturazione sensibili per PositiveInfinity e NegativeInfinity, in modo da poter rilevare l'overflow in un unchecked contesto. Per decimal, non esistono limiti di questo tipo e la saturazione in MaxValue può causare errori o confusione. Operazioni che usano decimal lanciano un'eccezione sia in un contesto checked che in un contesto unchecked.

Operazioni interessate dal contesto di controllo dell'overflow

Il contesto di controllo dell'overflow influisce sulle operazioni seguenti:

Il contesto predefinito per il controllo dell'overflow

Se non si specifica il contesto di controllo dell'overflow, il valore dell'opzione del compilatore CheckForOverflowUnderflow definisce il contesto predefinito per le espressioni non costanti. Per impostazione predefinita, il valore di tale opzione è unset e le operazioni aritmetiche di tipo integrale e le conversioni vengono eseguite in un contesto non verificato.

Le espressioni costanti vengono valutate per impostazione predefinita in un contesto controllato e l'overflow causa un errore in fase di compilazione. È possibile specificare in modo esplicito un contesto non verificato per un'espressione costante con l'istruzione o l'operatore unchecked.

Specifiche del linguaggio C#

Per altre informazioni, vedere le sezioni seguenti delle specifiche del linguaggio C#:

Vedi anche