将经过算术检查的语句放在哪里

本文关键字:语句 在哪里 检查 经过 | 更新日期: 2023-09-27 17:57:33

我正在读关于如何强制操作抛出溢出异常的文章,在"自己尝试"部分,我把它放在了与书不同的地方。我很好奇是否存在与某个位置相关的性能问题,因为我不确定checked关键字的基本机制。

书中的例子是做一个阶乘,它会很快引发溢出,即使是使用无符号的long。这是我想出的代码:

static long Factorial (long number) {
    long result = 1;
    for (int i = 2; i <= number; i++) {
        checked {
            result *= i;
        }
    }
    return result;
}

然而,从书后面的答案页来看,他们将checked包裹在函数的整个主体中,包括returnlong result = 1;。显然,在这些地方你永远不需要一个,所以如果有什么不同的话,我只需要将for循环封装在check中。

它在循环中的存在是否会导致某些底层CLR代码重复生成?(比如为什么在进入for循环之前声明一个变量。)或者循环中没有变量的开销?

将经过算术检查的语句放在哪里

编译后的结果不会有什么不同。

主要区别在于checked块内的任何算术运算都将使用不同的IL指令。没有更多的指令,只是不同的指令。你得到的不是mul,而是mul.ovf——而不是add,你得到的是add.ovf等。

然而,您的版本实际上具有略微不同的行为。由于您将checked块放在tigher作用域中,因此变量increment(i++)仍将被取消选中。原来的会一直被检查,这意味着i++可以抛出,而不仅仅是乘法运算。这确实意味着您的版本更快,但这只是因为您避免了溢出检查并更改了结果行为,而不是因为范围更改。

它在循环中的存在是否会导致某些底层CLR代码重复生成?

不,这只是意味着该范围内的那些IL指令将通过溢出检查而不是标准检查获得不同的IL操作代码。

或者在循环中没有开销?

没有开销(除了指令本身中检查的额外开销)。