C# 中算术溢出检查的最佳做法是什么?

本文关键字:是什么 最佳 溢出检查 | 更新日期: 2023-09-27 18:34:09

在 Web/stackoverflow 上有一些关于 'checked' 关键字与编译器选项"检查算术溢出/下溢"用法的好文章,比如:

http://www.codethinked.com/c-trivia-what-no-overflow

为什么 C# 默认不使用算术溢出检查?

在 C# 中处理整数溢出的最佳方法?

仍然不知道我应该使用哪一个。默认情况下,我更愿意使用编译器选项以始终安全,不要使用未选中的关键字弄乱我的代码,不要忘记它在某些地方,最后它不是很常用,所以可能不知道许多开发人员。

但是,我的实际性能打击有多糟糕?我想MS设置默认设置是不进行溢出检查是有充分理由的。编译器选项是否只涉及我的代码或每个使用的库和框架本身?

C# 中算术溢出检查的最佳做法是什么?

我有同样的问题。我更喜欢在我公司的代码中默认检查一段代码,因为溢出副作用可能花费很多并且难以诊断。发现这些副作用的真正原因可能是有价值的。

问题是,我们在性能方面失去了什么?

这是一个非常简单的长凳:

static void Main(string[] args)
{
    long c = 0;
    var sw = new Stopwatch();
    sw.Start();
    unchecked
    {
        for (long i = 0; i < 500000000; i++) c += 1;
    }
    sw.Stop();
    Console.WriteLine("Unchecked: " + sw.ElapsedMilliseconds);
    c = 0;
    sw.Restart();
    checked
    {
        for (long i = 0; i < 500000000; i++) c += 1;
    }
    sw.Stop();
    Console.WriteLine("Checked: " + sw.ElapsedMilliseconds);
}

在生成的 IL 中,我看到选中和未选中的关键字决定了是否将使用 add.ovf添加指令。(适用于调试和发布配置(

IL_001c:  ldloc.2
IL_001d:  ldc.i4.1
IL_001e:  conv.i8
IL_001f:  add

IL_0066:  ldloc.2
IL_0067:  ldc.i4.1
IL_0068:  conv.i8
IL_0069:  add.ovf

结果(x64 主机(

调试

  • 未选中:2371
  • 检查: 2437

释放

  • 未选中:2088
  • 检查: 2266

long(s( 替换为 int(x64 主机(的其他结果

调试

  • 未选中:1665
  • 检查: 1568

释放

  • 未选中:189
  • 检查: 566

性能影响就在那里,看起来选择正确的变量类型更重要,可以选中或取消选中。无论如何,这不会改变我的观点。我将在我们所有的项目中打开"检查算术溢出/下溢"!(高级构建设置(。

当需要性能时,我将简单地使用未经检查的块。