Проверяемые и непроверяемые операции
для примитивных типов
Программистам должно быть хорошо известно, что многие арифметические опе-
рации над примитивными типами могут привести к переполнению:
Byte b = 100;
b = (Byte) (b + 200);// После этого b равно 44 (2C в шестнадцатеричной записи)
Такое «незаметное» переполнение обычно в программировании не приветству-
ется, и если его не выявить, приложение поведет себя непредсказуемо. Изредка,
правда (например, при вычислении хеш-кодов или контрольных сумм), такое
переполнение не только приемлемо, но и желательно.
147
Примитивные.типы.в.языках.программирования
ВниМание
При.выполнении.этой.арифметической.операции.CLR.на.первом.шаге.все.значения.
операндов.расширяются.до.32.разрядов.(или.64.разрядов,.если.для.представления.
операнда.32.разрядов.недостаточно) .Поэтому.b.и.200.(для.которых.32.разрядов.
достаточно).сначала.преобразуются.в.32-разрядные.значения,.а.затем.уже.сумми-
руются .Полученное.32-разрядное.число.(300.в.десятичной.системе,.12C.в.шестна-
дцатеричной),.прежде.чем.поместить.его.обратно.в.переменную.b,.нужно.привести.
к.типу.Byte .Так.как.в.данном.случае.C#.не.выполняет.неявного.приведения.типа,.во.
вторую.строку.введена.операция.приведения.к.типу.Byte
В каждом языке существуют свои способы обработки переполнения. В C и C++
переполнение ошибкой не считается, а при усечении значений приложение не пре-
рвет свою работу. А вот в Visual Basic переполнение всегда рассматривается как
ошибка, и при его обнаружении генерируется исключение.
В CLR есть IL-команды, позволяющие компилятору по-разному реагировать
на переполнение. Например, суммирование двух чисел выполняет команда
add
, не
реагирующая на переполнение, а также команда
add.ovf
, которая при переполне-
нии генерирует исключение
System.OverflowException
. Кроме того, в CLR есть
аналогичные IL-команды для вычитания (
sub/sub.ovf
), умножения (
mul/mul.ovf
)
и преобразования данных (
conv/conv.ovf
).
Пишущий на C# программист может сам решать, как обрабатывать переполне-
ние; по умолчанию проверка переполнения отключена. Это значит, что компилятор
генерирует для операций сложения, вычитания, умножения и преобразования IL-
команды без проверки переполнения. В результате код выполняется быстро, но раз-
работчик должен быть либо уверен в отсутствии переполнения, либо предусмотреть
возможность его возникновения в своем коде.
Чтобы включить механизм управления процессом обработки переполне-
ния на этапе компиляции, добавьте в командную строку компилятора параметр
/checked+
. Он сообщает компилятору, что для выполнения сложения, вычитания,
умножения и преобразования должны быть сгенерированы IL-команды с проверкой
переполнения. Такой код медленнее, так как CLR тратит время на проверку этих
операций, ожидая переполнение. Когда оно возникает, CLR генерирует исключе-
ние
OverflowException
. Код приложения должен предусматривать корректную
обработку этого исключения.
Однако программистам вряд ли понравится необходимость включения или от-
ключения режима проверки переполнения во всем коде. Им лучше самим решать, как
реагировать на переполнение в каждом конкретном случае. И C# предлагает такой
механизм гибкого управления проверкой в виде операторов
checked
и
unchecked
. На-
пример (предполагается, что компилятор по умолчанию создает код без проверки):
UInt32 invalid = unchecked((UInt32) -1); // OK
А вот пример с использованием оператора
checked
:
Byte b = 100; // Выдается исключение
b = checked((Byte) (b + 200)); // OverflowException
148
Do'stlaringiz bilan baham: |