C#内联检查语句不起作用

时间:2017-08-22 07:57:30

标签: c# casting exception-handling

我有两种测试方法。第一个工作正常。第二个不会抛出异常,但它应该。为什么第二个没有抛出异常?

[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?
}

3 个答案:

答案 0 :(得分:25)

第一个抛出的原因和第二个抛出的原因是因为你的比较有点偏差。

  • 在第一种方法中check一切
  • 在第二种方法中,您只需checklong转换为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 )int maxValue添加1(此处发生例外),之后 将其分配给{{1} },如果您在添加1之前long castint,则不会抛出:

long

答案 1 :(得分:8)

正如MSDN document所说

  

已检查 关键字用于显式启用溢出检查   积分型算术运算和转换。

第一个测试方法已经在检查 声明的块 中是否存在溢出值。

enter image description here

第二种测试方法只检查溢出值 这行代码。

  

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

enter image description here

由于溢出发生在checked表达式之前,因此CLR已经转换了该值。 而且值为-2147483648 which is legal,因为int范围是 enter image description here

有什么区别?

测试方法1:已检查块

测试方法2:检查表达

答案 2 :(得分:2)

因为您将其转换为long。未经检查的(maxValue + 1)会导致-2147483648中存储long {{}}},然后转回int。因此,在最终投放intValue商店-2147483648

之后

相反,请尝试以下操作,这将导致OverflowException

 int intValue = checked(maxValue + 1);

(或)甚至

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