С# inline checked statement не работает

У меня есть два метода тестирования. Первый работает отлично. Второй не вызывает исключения, но должен. Почему вторая исключает исключение?

[TestMethod]
[ExpectedException(typeof(OverflowException))]
public void LongToInt_OverflowWithCheckedBlock()
{
    checked
    {
        int maxValue = 2147483647;
        long longValue = (maxValue + 1);
        int intValue = (int)longValue;
    }
}

[TestMethod]
[ExpectedException(typeof(OverflowException))]
public void LongToInt_OverflowWithCheckedStatement()
{

    int maxValue = 2147483647;
    long longValue = (maxValue + 1);
    int intValue = checked((int)longValue);     // No Exception is thrown, why?
}

Ответы

Ответ 1

Причина, по которой первый бросает, а второй - нет, потому что ваше сравнение немного выключено.

  • В первом методе вы check все
  • Во втором методе вы check выполняете только от long до int.

Если вы сравниваете их, как показано ниже, они равны и не будут бросать:

private static void MethodA()
{
    int maxValue = 2147483647;
    long longValue = ( maxValue + 1 );
    checked
    {
        int intValue = ( int ) longValue;
    }
}

private static void MethodB()
{
    int maxValue = 2147483647;
    long longValue = ( maxValue + 1 );
    int intValue = checked( ( int ) longValue);
}

Причиной этого является то, что эта строка: int intValue = checked(( int ) longValue); не та, которая бросает, ее эта строка:

long longValue = ( maxValue + 1 );

Если я поставлю проверочный флажок, они оба бросят:

long longValue = checked( maxValue + 1 );

Почему он выбрасывает здесь:

Он выдает, потому что ( maxValue + 1 ) добавляет 1 к int, называемому maxValue (здесь происходит исключение) и после этого назначает его long, если вы cast int до long, прежде чем делать добавление 1, он не будет бросать:

long longValue = ( (long) maxValue + 1 );

Ответ 2

Как документ MSDN сказал,

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

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

введите описание изображения здесь

Второй метод тестирования проверяет только переполняющее значение только эту строку кода.

int intValue = checked((int)longValue); //Checked expression

введите описание изображения здесь

Так как переполнение происходит перед выражением checked, CLR уже преобразовал значение. И это значение -2147483648 которое является законным, поскольку int range введите описание изображения здесь

В чем разница?

Метод теста 1: Проверенный блок

Метод тестирования 2: Проверенное выражение

Ответ 3

Это означает, что вы конвертируете его в long. Непроверенный (maxValue + 1) приводит к -2147483648, который вы сохраняете в long и в свою очередь отбрасываете обратно на int. Таким образом, после окончательного добавления ваши intValue магазины -2147483648

Вместо этого попробуйте, как показано ниже, и это приведет к OverflowException

 int intValue = checked(maxValue + 1);

(или) даже

long longValue = checked((maxValue + 1));