С# 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));