Поделиться через


Проверенные и непроверенные операции (справочник по C#)

Операторы checked и unchecked указывают контекст проверки переполнения для арифметических операций и преобразований целочисленного типа. Оператор по умолчанию unchecked. Когда происходит арифметическое переполнение, контекст проверки переполнения определяет, что происходит. В проверяемом контексте выбрасывается System.OverflowException; если в константном выражении происходит переполнение, во время компиляции возникает ошибка. В непроверенном контексте результат операции усечен путем удаления любых битов высокого порядка, которые не соответствуют целевому типу. Например, сложение переходит от максимального значения к минимальному значению. В следующем примере показана одна и та же операция в проверенном и непроверенном контексте:

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

Примечание.

Поведение переполнения определяемых пользователем операторов и преобразований может отличаться от того, что описано в предыдущем абзаце. В частности, определяемые пользователем операторы могут не вызывать исключение в проверяемом контексте.

Дополнительные сведения см. в разделах Арифметическое переполнение и деление на ноль и Дефинированные пользователем проверяемые операторы статьи Арифметические операторы.

Чтобы указать контекст проверки переполнения для выражения, можно также использовать операторы checked и unchecked, как показано в следующем примере.

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

Операторы checked и unchecked влияют только на контекст проверки переполнения для операций, которые находятся текстуально внутри блока оператора или в круглых скобках, как показано в следующем примере:

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

В предыдущем примере первый вызов локальной Multiply функции показывает, что инструкция checked не влияет на контекст проверки на переполнение в функции Multiply, поскольку исключение не выбрасывается. При втором вызове функции Multiply, выражение, которое вычисляет второй аргумент функции, вычисляется в проверяемом контексте и приводит к исключению, так как оно находится текстуально внутри блока инструкции checked.

Поведение checked и unchecked зависит от типа и операции. Даже для целых чисел такие операции, как unchecked(x / 0), всегда вызывают ошибку, потому что нет разумного поведения. Проверьте поведение типа и операции, чтобы понять, как checkedunchecked ключевые слова влияют на код.

Числовые типы и контекст проверки переполнения

Ключевые слова checked и unchecked в основном применяются к целочисленным типам, где существует адекватное поведение переполнения. Поведение обходного пути, в котором T.MaxValue + 1 становится T.MinValue разумным в двух дополнительных значениях. Представленное значение неправильно, так как оно не может поместиться в хранилище для типа. Таким образом, биты представляют собой более низкие n-биты полного результата.

Для таких типов, как decimal, floatdoubleи Half которые представляют более сложное значение или дополнительное значение, оболочка не является разумной. Его нельзя использовать для вычисления больших или более точных результатов, поэтому unchecked это не полезно.

float, doubleи Half имеют разумные насыщенные значения для PositiveInfinity и NegativeInfinity, чтобы можно было обнаружить переполнение в контексте unchecked . Таких ограничений для decimal не существует, а насыщение на MaxValue может привести к ошибкам или путанице. Операции, использующие decimal, выбрасывают исключения как в контексте checked, так и в unchecked.

Операции, затронутые контекстом проверки переполнения

Контекст проверки переполнения влияет на следующие операции:

Контекст проверки переполнения по умолчанию

Если контекст проверки переполнения не указан, значение параметра компилятора CheckForOverflowUnderflow определяет контекст по умолчанию для неконстантных выражений. По умолчанию значение этого параметра не задано, а целочисленные арифметические операции и преобразования выполняются в неконтролируемом контексте.

Константные выражения вычисляются по умолчанию в проверяемом контексте и переполнении вызывают ошибку во время компиляции. Вы можете явно указать непроверенный контекст для константного выражения с помощью оператора или выражения unchecked.

Спецификация языка C#

Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#:

См. также