As instruções verificadas e não verificadas (referência C#)
As checked
instruções and unchecked
especificam o contexto de verificação de estouro para operações aritméticas de tipo integral e conversões. Quando ocorre estouro aritmético inteiro, o contexto de verificação de estouro define o que acontece. Em um contexto verificado, um é lançado: se o System.OverflowException estouro acontece em uma expressão constante, ocorre um erro em tempo de compilação. Em um contexto não verificado, o resultado da operação é truncado descartando quaisquer bits de ordem alta que não se encaixam no tipo de destino. Por exemplo, a adição envolve do valor máximo para o valor mínimo. O exemplo a seguir 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.
}
Nota
O comportamento de estouro de operadores definidos pelo usuário e conversões pode diferir do descrito no parágrafo anterior. Em particular, os operadores verificados definidos pelo usuário podem não lançar 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 checked
operadores and 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.
}
As checked
instruções e operadores e unchecked
afetam apenas o contexto de verificação de estouro para as operações que estão textualmente dentro do bloco de instrução ou parênteses do operador, 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 mostra que a checked
instrução não afeta o contexto de verificação de Multiply
estouro dentro da função, Multiply
pois nenhuma exceção é lançada. Na segunda invocação da Multiply
função, 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 checked
instrução.
O comportamento de checked
e unchecked
depende do tipo e da operação. Mesmo para números inteiros, operações como unchecked(x / 0)
sempre lançam porque não há um comportamento sensato. Verifique o comportamento do tipo e da operação para entender como as palavras-chave afetam unchecked
seu checked
código.
Tipos numéricos e contexto de verificação de estouro
As checked
palavras-chave e unchecked
aplicam-se principalmente a tipos integrais onde há um comportamento de estouro sensato. O comportamento envolvente onde T.MaxValue + 1
se torna T.MinValue
é sensível no valor do complemento de um dois. O valor representado não está correto , pois não cabe no armazenamento do tipo. Portanto, os bits são representativos dos n-bits inferiores do resultado completo.
Para tipos como decimal
, float
, double
, e Half
que representam um valor mais complexo ou um valor de complemento, o wraparound não é sensato. Ele não pode ser usado para calcular resultados maiores ou mais precisos, por isso unchecked
não é benéfico.
float
, double
e Half
têm valores de saturação sensíveis para e NegativeInfinity
, para PositiveInfinity
que você possa detetar estouro em um unchecked
contexto. Pois decimal
não existem tais limites, e a saturação pode MaxValue
levar a erros ou confusão. As operações que usam decimal
o lançamento em um checked
e unchecked
no contexto.
Operações afetadas pelo contexto de verificação de estouro
O contexto de verificação de estouro afeta as seguintes operações:
Os seguintes operadores aritméticos internos: unário
++
,--
,-
e binário+
,-
,*
, e/
operadores, quando seus operandos são de um tipo integral (isto é, numérico integral ou tipo char) ou um tipo enum.Conversões numéricas explícitas entre tipos integrais ou de
float
oudouble
para um tipo integral.Nota
Quando você converte um
decimal
valor em um tipo integral e o resultado está fora do intervalo do tipo de destino, um OverflowException é sempre lançado, independentemente do contexto de verificação de estouro.A partir do C# 11, operadores e conversões verificados definidos pelo usuário. Para obter mais informações, consulte a seção Operadores verificados definidos pelo usuário do artigo Operadores aritméticos.
Contexto padrão de verificação de estouro
Se você não especificar o contexto de verificação de estouro, o valor da opção de compilador CheckForOverflowUnderflow definirá o contexto padrão para expressões não constantes. Por padrão, o valor dessa opção é desdefinido e operações aritméticas de tipo integral e 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 em tempo de compilação. Você pode especificar explicitamente um contexto não verificado para uma expressão constante com a unchecked
instrução ou operador.
Especificação da linguagem C#
Para obter mais informações, consulte as seguintes seções da especificação da linguagem C#:
- As declarações verificadas e não verificadas
- Os operadores controlados e não controlados
- Operadores verificados e não verificados definidos pelo usuário - C# 11