Compartilhar via


As instruções checked e unchecked (referência de C#)

As instruções checked e unchecked especificam o contexto de verificação de estouro para operações e conversões aritméticas do tipo integral. A instrução padrão é unchecked. Quando ocorre um estouro aritmético inteiro, o contexto de verificação de estouro define o que acontece. Em um contexto verificado, um System.OverflowException é lançado; se o estouro acontece em uma expressão de constante, ocorre um erro em tempo de compilação. Em um contexto não verificado, o resultado da operação é truncado pelo descarte dos bits de ordem superior que não se ajustam ao tipo de destino. Por exemplo, a adição passa do valor máximo para o valor mínimo. O seguinte exemplo mostra a mesma operação em um contexto verificado e não verificado:

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.
}

Observação

O comportamento de estouro dos operadores e das conversões definidos pelo usuário pode ser diferente daquele descrito no parágrafo anterior. Em particular, os operadores verificados definidos pelo usuário podem não gerar uma exceção em um contexto verificado.

Para obter mais informações, consulte as seções Estouro aritmético e divisão por zero e Operadores verificados definidos pelo usuário do artigo Operadores aritméticos.

Para especificar o contexto de verificação de estouro para uma expressão, você também pode usar os operadores checked e unchecked, como mostra o exemplo a seguir:

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.
}

Os operadores e as instruções checked e unchecked afetam apenas o contexto de verificação de estouro para as operações que estão textualmente dentro dos parênteses do operador ou do bloco de instrução, como mostra o exemplo a seguir:

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.
}

No exemplo anterior, a primeira invocação da função local Multiply mostra que a instrução checked não afeta o contexto de verificação de estouro dentro da função Multiply, pois nenhuma exceção é gerada. Na segunda invocação da função Multiply, a expressão que calcula o segundo argumento da função é avaliada em um contexto verificado e resulta em uma exceção, pois está textualmente dentro do bloco da instrução checked.

O comportamento de checked e unchecked depende do tipo e da operação. Mesmo para inteiros, as operações como unchecked(x / 0) sempre geram um erro porque não há comportamento sensato. Verifique o comportamento do tipo e da operação para entender como as checked palavras-chave e unchecked afetam seu código.

Tipos numéricos e contexto de verificação de estouro

As palavras-chave checked e unchecked se aplicam principalmente aos tipos integrais, onde o comportamento de estouro é gerido de forma adequada. O comportamento de encapsulamento onde T.MaxValue + 1 se torna T.MinValue é sensato no valor do complemento de dois. O valor representado não está correto , uma vez que não se ajusta ao armazenamento para o tipo. Portanto, os bits são representativos dos n bits mais baixos do resultado completo.

Para tipos como decimal, float, double e Half que representam um valor mais complexo ou o valor de complemento de um, o encapsulamento não é sensato. Ele não pode ser usado para calcular resultados maiores ou mais precisos, portanto unchecked , não é benéfico.

float, double, e Half têm valores de saturação sensatos para PositiveInfinity e NegativeInfinity, para que você possa detectar estouro em um unchecked contexto. Para decimal, não existem tais limites, e saturar em MaxValue pode levar a erros ou confusão. As operações que usam decimal geram uma exceção tanto em um contexto checked como em um contexto unchecked.

Operações afetadas pelo contexto de verificação de estouro

O contexto de verificação de estouro afeta as seguintes operações:

Contexto de verificação de estouro padrão

Se você não especificar o contexto de verificação de estouro, o valor da opção do compilador CheckForOverflowUnderflow define o contexto padrão para expressões não constantes. Por padrão, o valor dessa opção não é definido, e as operações aritméticas de tipo integral e as conversões são executadas em um contexto não verificado.

As expressões constantes são avaliadas por padrão em um contexto verificado, e o estouro causa um erro de compilação. Você pode especificar explicitamente um contexto não verificado para uma expressão constante com o operador ou a instrução unchecked.

Especificação da linguagem C#

Para obter mais informações, confira as seguintes seções da especificação da linguagem C#:

Confira também