我正在阅读有关如何强制执行操作以抛出溢出异常的问题,并且在#34;自己试试"部分,我把它放在与书不同的地方。我很好奇是否存在与某个地点相关的性能问题,因为我不确定checked
关键字的基本机制。
本书中的例子是做一个阶乘,即使使用无符号长整数也会快速抛出溢出。这是我提出的代码:
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循环之前声明一个变量一样。)或者在循环中没有开销吗?
答案 0 :(得分:4)
编译结果方面差别不大。
主要区别在于checked
块内的任何算术运算都将使用不同的IL指令。没有更多指令,只是不同的指令。不是mul
,而是mul.ovf
- 而不是add
,而是获得add.ovf
等。
但是,您的版本实际上的行为略有不同。由于您将checked
块放在更大的范围内,因此仍将取消选中变量增量(i++
)。原始版本将一直被检查,这意味着i++
可以抛出,而不仅仅是乘法运算。这确实意味着您的版本更快,但这只是因为您避免了溢出检查并更改了结果行为,而不是因为范围更改。
它是否存在于循环内导致一些底层CLR代码重复生成?
不,它只是意味着该范围内的那些IL指令将获得具有溢出检查的不同IL操作代码而不是标准的。
或者循环中是否没有开销?
没有开销(除了指令本身的检查额外开销)。