Почему это не вызывает исключение переполнения?

Я тестировал что-то с помощью LinqPad и был удивлен, что следующий код не выдал исключение:

ulong lSmallValue = 5;
ulong lBigValue = 10;

ulong lDifference = lSmallValue - lBigValue;

Console.WriteLine(lDifference);
Console.WriteLine((long)lDifference);

Это дает следующий результат:

18446744073709551611
-5

К счастью, я надеялся на такое поведение, но предполагал, что это приведет к выдаче OverflowException.

Из System.OverflowException:

Исключение OverflowException возникает во время выполнения при следующих условиях:

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

Почему операция lSmallValue - lBigValue не относится к первой категории?


person Anthony    schedule 24.09.2012    source источник
comment
Вероятно, он не вне диапазона; ulong по-прежнему имеет достаточно битов для хранения значений вашей операции (хотя это интерпретируется иначе, чем вы ожидаете).   -  person Uwe Keim    schedule 24.09.2012


Ответы (2)


CLR не будет вызывать исключение переполнения по умолчанию. Если только вы не используете ключевое слово "checked".

http://msdn.microsoft.com/en-us/library/74b4xzyw%28v=vs.71%29.aspx

UPD: На самом деле, я рекомендую "CLR через C#" Джеффри Рихтера - он делает эти вещи намного более прозрачными. Моя любимая книга об основах CLR и C#.

person Mikhail    schedule 24.09.2012
comment
На самом деле это приводит к возникновению исключения. Спасибо, я никогда раньше не сталкивался с ключевым словом checked. - person Anthony; 24.09.2012

«Чтобы арифметическая операция, приведение или преобразование вызывали исключение OverflowException, операция должна выполняться в проверенном контексте».

Исключение OverflowException будет вызвано, как только вы поместите свой код в проверенный блок.

ulong lSmallValue = 5;
ulong lBigValue = 10;
checked {
try {
    ulong lDifference = lSmallValue - lBigValue;
}
catch (OverflowException) {
    Console.WriteLine("Exception caught");
}}
person Mark    schedule 24.09.2012
comment
Это неправильно, если я оберну его в блок try..catch в LinqPad, все равно не будет выдано исключение. - person Anthony; 24.09.2012
comment
Checked в данном случае не имеет ничего общего с try/catch. Существует блок checked { }, iirc, который включает проверку переполнения. - person cHao; 24.09.2012
comment
Я не думаю, что это правильный ответ - try catch не имеет никакого смысла. Вам нужно использовать ключевое слово cehcked. Смотрите мой ответ ниже - person Mikhail; 24.09.2012
comment
-1 Это неправильно. Checked context не имеет ничего общего с try/catch, а имеет отношение только к запуску в блоке checked. unchecked контекст используется по умолчанию. - person Chris Hannon; 24.09.2012
comment
Я не получаю никаких исключений, когда этот код находится внутри блока try..catch. - person Gromer; 24.09.2012
comment
Упс, конечно. Требуется проверенный контекст. Я адаптировал текст. - person Mark; 24.09.2012