Почему я должен явно окружать «непроверенным»? - PullRequest
10 голосов
/ 19 октября 2011

Кто-нибудь может объяснить мне это странное поведение?

    int i = 0x1234;
    byte b1 = (byte)i;
    byte b2 = (byte)0x1234;         //error: const value '4660' can't convert to byte (use unchecked)
    byte b3 = unchecked((byte)0x1234);
    byte b4 = checked((byte)i);     //throws
    byte b5 = (byte)(int)0x1234;    //error: same as above

ПРИМЕЧАНИЕ. Это пустое консольное приложение с включенной NO арифметической проверкой (по умолчанию). Спасибо всем заранее.

РЕДАКТИРОВАТЬ: Я должен был быть достаточно ясным, но не для всех.

Я знаю, что слово не может вписаться в байт. Но по умолчанию программа на C # допускает некоторые «опасные» операции, в основном из соображений производительности.

Точно так же я могу сложить два больших целых числа без переполнения.

Мое удивление было связано с ошибкой во время компиляции, приведенной выше: приведение / назначение b1 скомпилировано, b2 не может скомпилироваться. Очевидно, нет никакой разницы, потому что оба Int32 имеют одинаковое значение.

Надеюсь, теперь все ясно.

Ответы [ 3 ]

13 голосов
/ 19 октября 2011

Вы отключаете часть раздела 7.19 спецификации C # 4:

Если постоянное выражение явно не помещено в контекст unchecked, переполнения происходят в арифметике целочисленного типаОперации и преобразования во время вычисления выражения во время компиляции всегда вызывают ошибки во время компиляции.

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

Например, в этом случае вы теряете информацию - она ​​будет эквивалентна

byte b3 = 0x34;

, поэтому вам обычно будет лучше просто указатьчтобы дать вам более понятный код, который не вводит читателя в заблуждение.Относительно редко вы хотите переполнить константу - большую часть времени вам просто нужно вместо этого указать действительное значение.

1 голос
/ 19 октября 2011

Вы не должны окружать это непроверенным. Не отмечено позволяет присваивать типам опасные значения для типа, что может привести к переполнению.

byte b1 = (byte)i; вызовет переполнение или исключение приведения во время выполнения.

byte b2 = (byte)0x1234; недопустимо, поскольку вы не можете хранить значения больше 0xFF в байте.

byte b3 = unchecked((byte)0x1234); поместит 0x34 или 0x12 (в зависимости от реализации CLR) в b3, а другой байт будет переполнен.

byte b4 = checked((byte)i); совпадает с byte b1 = (byte)i;

byte b5 = (byte)(int)0x1234; приведёт 0x1234 к int, а затем попытается привести его к байту. Опять же, вы не можете преобразовать 0x1234 в байт, потому что он слишком большой.

1 голос
/ 19 октября 2011

Это не странное поведение, допустимый диапазон для переменной типа данных byte равен 0-255, но при преобразовании значения HEX 0x1234 в десятичную систему вы получаете 4660. Поэтому не проверено используется для управления арифметическими операциями и преобразованиями целочисленного типа с проверкой переполнения.

Вы можете обнаружить, что unchecked часто используется в реализации GetHashCode(), которая выполняет числовые операции для вычисления окончательного хеш-кода.

Для подведения итогов следует использовать unchecked, когда конечное значение результата целочисленных операций не имеет значения, но может произойти переполнение.

...