Нет исключения переполнения для int в C #? - PullRequest
56 голосов
/ 13 января 2010

У меня был странный опыт с проблемой № 10 на Project Euler (кстати, отличный сайт). Задание состояло в том, чтобы вычислить сумму всех простых чисел ниже двух миллионов.

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

Оказалось, что результат слишком велик, чтобы поместиться в int, но не приведет ли это к ошибке переполнения или к чему-то еще? Вместо этого он просто возвратил значение, далекое от реального ответа.

Когда я сменил тип на long, все было просто шикарно.

Ответы [ 5 ]

86 голосов
/ 13 января 2010

Целочисленные операции C # по умолчанию не вызывают исключений при переполнении. Этого можно добиться с помощью настроек проекта или расчета checked:

int result = checked(largeInt + otherLargeInt);

Теперь операция скинет.

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

19 голосов
/ 13 января 2010

В C # OverflowException не генерируется (в VB исключение выдается по умолчанию).

Чтобы получить исключение, вы должны встроить свой код в checked контекст:

byte value = 241;
checked
{
    try 
    {
        sbyte newValue = (sbyte) value;
        Console.WriteLine("Converted the {0} value {1} to the {2} value {3}.", 
            value.GetType().Name, value, 
            newValue.GetType().Name, newValue);
    }
    catch (OverflowException) 
    {
        Console.WriteLine("Exception: {0} > {1}.", value, SByte.MaxValue);
    }
}       

MSDN объясняет более подробно:

Для арифметики, кастинга или операция преобразования, чтобы бросить OverflowException, операция должна происходят в проверенном контексте. От по умолчанию, арифметические операции и переполнения в Visual Basic проверяются; в C # их нет. Если операция происходит в неконтролируемом контексте, результат усекается путем отбрасывания любого старшие биты, которые не вписываются в тип назначения.

14 голосов
/ 02 апреля 2015

Это потому, что по умолчанию C # не генерирует никаких исключений для целочисленного переполнения, а также для переполнения. Здесь можно сделать несколько вещей.

Вариант 1

Вы должны включить исключение, перейдя в Project => properties => вкладка Build => Advanced => проверка на арифметическое переполнение (убедитесь, что вы отметили опцию)

enter image description here

Убедитесь, что вы отметили опцию

Вариант 2

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

        try
        {
            checked
            {
                int y = 1000000000;
                short x = (short)y;
            }
        }
        catch (OverflowException ex)
        {
            MessageBox.Show("Overflow");
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error");
        }

Надеюсь, это поможет вам ...:)

7 голосов
/ 13 января 2010

Я уже добавил cmt, но для некоторых из вас это может быть интересно:

msdn говорит нам:

Целочисленное арифметическое переполнение либо генерирует OverflowException или отбрасывает наиболее значимые биты результат

но

Десятичное арифметическое переполнение всегда создает исключение OverflowException.

также

Когда происходит целочисленное переполнение, что бывает зависит от исполнения контекст, который может быть проверен или бесконтрольно. В проверенном контексте Выдается OverflowException. В непроверенный контекст, наиболее значимые биты результата отбрасывается и исполнение продолжается. Таким образом, C # дает вам выбор обработка или игнорирование переполнения.

6 голосов
/ 13 января 2010

По умолчанию C # не проверяет арифметическое переполнение на целых числах. Вы можете изменить это с помощью опции компилятора /checked или включив «Проверка на арифметическое переполнение / переполнение» в Visual Studio (свойства проекта - Build - Advanced).

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

int j = checked(i * 2);

checked
{
    int j = i * 2;
    // Do more stuff
}

Обратите внимание, что операции с плавающей точкой никогда не выдают OverflowException, а десятичные операции всегда выдают OverflowException. Смотрите также C # операторы .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...