【问题标题】:Where to put an arithmetic checked statement?在哪里放置算术检查语句?
【发布时间】:2014-04-09 16:44:54
【问题描述】:

我正在阅读有关如何强制操作引发溢出异常的信息,在“自己尝试”部分,我将它放在与书不同的地方。我很好奇是否存在与某个位置相关的性能问题,因为我不确定 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 循环之前声明一个变量。)或者在循环中没有开销?

【问题讨论】:

    标签: c# performance math overflowexception


    【解决方案1】:

    就编译结果而言,差别不大。

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

    但是,您的版本实际上具有略微不同的行为。由于您将checked 块放在更窄的范围内,因此变量增量(i++)仍将处于未选中状态。原件将一直被检查,这意味着i++ 可以抛出,而不仅仅是乘法运算。这确实意味着您的版本更快,但这只是因为您避免了溢出检查并更改了结果行为,而不是因为范围更改。

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

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

    或者在循环中没有开销?

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

    【讨论】:

    • 这实际上是我的代码的一个很好的整体捕获。如果参数大于 int32.MaxValue,那么我也会溢出。
    • @krillgar 是的 - 我进行了编辑以包含更多指向详细信息的链接等。基本上,它只是改变了编译器在这些位置生成指令的方式,但实际上并没有添加额外的 IL 操作码。跨度>
    • 谢谢,额外的细节确实有助于理解发生了什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-25
    • 1970-01-01
    • 2012-04-21
    相关资源
    最近更新 更多