Проверенные и снятые операторы (справочник по C#)
unchecked
Операторы checked
указывают контекст проверки переполнения для арифметических операций и преобразований целочисленного типа. Когда происходит арифметическое арифметическое переполнение, контекст проверки переполнения определяет, что происходит. В проверяемом контексте возникает исключение; 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)
всегда, бросают, потому что нет разумного поведения. Проверьте поведение типа и операции, чтобы понять, как checked
unchecked
ключевые слова влияют на код.
Числовые типы и контекст проверки переполнения
unchecked
Ключевые checked
слова в основном применяются к целочисленным типам, где есть разумное поведение переполнения. Поведение обходного пути, в котором T.MaxValue + 1
становится T.MinValue
разумным в двух дополнительных значениях. Представленное значение неправильно, так как оно не может поместиться в хранилище для типа. Таким образом, биты представляют собой более низкие n-биты полного результата.
Для таких типов, как decimal
, float
double
и Half
которые представляют более сложное значение или дополнительное значение, оболочка не является разумной. Его нельзя использовать для вычисления больших или более точных результатов, поэтому unchecked
это не полезно.
float
, double
и Half
имеют разумные насыщенные значения для PositiveInfinity
и NegativeInfinity
, чтобы можно было обнаружить переполнение в контексте unchecked
. Для decimal
этого не существует таких ограничений, а насыщенность MaxValue
может привести к ошибкам или путанице. Операции, использующие decimal
вызов как в контексте checked
, так и unchecked
в контексте.
Операции, затронутые контекстом проверки переполнения
Контекст проверки переполнения влияет на следующие операции:
Следующие встроенные арифметические операторы: унарные
++
,--
-
и двоичные+
-
,*
и/
операторы, когда их операнды имеют целочисленный тип (то есть целочисленный или тип символа) или тип перечисления.Явные числовые преобразования между целочисленными типами или от или
double
доfloat
целочисленного типа.Примечание.
При преобразовании
decimal
значения в целочисленный тип и результат находится за пределами диапазона целевого типа, OverflowException всегда создается независимо от контекста проверки переполнения.Начиная с C# 11, определяемые пользователем операторы и преобразования. Дополнительные сведения см. в разделе Проверенные операторы, определяемые пользователем статьи Арифметические операторы.
Контекст проверки переполнения по умолчанию
Если контекст проверки переполнения не указан, значение параметра компилятора CheckForOverflowUnderflow определяет контекст по умолчанию для неконстантных выражений. По умолчанию значение этого параметра не задано, а арифметические операции целочисленного типа и преобразования выполняются в неконтролируемом контексте.
Константные выражения вычисляются по умолчанию в проверяемом контексте и переполнении вызывают ошибку во время компиляции. Вы можете явно указать без флажок контекст для константного выражения с оператором или оператором unchecked
.
Спецификация языка C#
Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#:
- Операторы checked и unchecked
- Операторы checked и unchecked
- Определяемые пользователем операторы с проверкой и отменой проверки — C# 11