将经过算术检查的语句放在哪里
本文关键字:语句 在哪里 检查 经过 | 更新日期: 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
包裹在函数的整个主体中,包括return
和long result = 1;
。显然,在这些地方你永远不需要一个,所以如果有什么不同的话,我只需要将for
循环封装在check
中。
它在循环中的存在是否会导致某些底层CLR代码重复生成?(比如为什么在进入for循环之前声明一个变量。)或者循环中没有变量的开销?
编译后的结果不会有什么不同。
主要区别在于checked
块内的任何算术运算都将使用不同的IL指令。没有更多的指令,只是不同的指令。你得到的不是mul
,而是mul.ovf
——而不是add
,你得到的是add.ovf
等。
然而,您的版本实际上具有略微不同的行为。由于您将checked
块放在tigher作用域中,因此变量increment(i++
)仍将被取消选中。原来的会一直被检查,这意味着i++
可以抛出,而不仅仅是乘法运算。这确实意味着您的版本更快,但这只是因为您避免了溢出检查并更改了结果行为,而不是因为范围更改。
它在循环中的存在是否会导致某些底层CLR代码重复生成?
不,这只是意味着该范围内的那些IL指令将通过溢出检查而不是标准检查获得不同的IL操作代码。
或者在循环中没有开销?
没有开销(除了指令本身中检查的额外开销)。