C# 中算术溢出检查的最佳做法是什么?
本文关键字:是什么 最佳 溢出检查 | 更新日期: 2023-09-27 18:34:09
在 Web/stackoverflow 上有一些关于 'checked' 关键字与编译器选项"检查算术溢出/下溢"用法的好文章,比如:
http://www.codethinked.com/c-trivia-what-no-overflow
为什么 C# 默认不使用算术溢出检查?
在 C# 中处理整数溢出的最佳方法?
我仍然不知道我应该使用哪一个。默认情况下,我更愿意使用编译器选项以始终安全,不要使用未选中的关键字弄乱我的代码,不要忘记它在某些地方,最后它不是很常用,所以可能不知道许多开发人员。
但是,我的实际性能打击有多糟糕?我想MS设置默认设置是不进行溢出检查是有充分理由的。编译器选项是否只涉及我的代码或每个使用的库和框架本身?
我有同样的问题。我更喜欢在我公司的代码中默认检查一段代码,因为溢出副作用可能花费很多并且难以诊断。发现这些副作用的真正原因可能是有价值的。
问题是,我们在性能方面失去了什么?
这是一个非常简单的长凳:
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
性能影响就在那里,看起来选择正确的变量类型更重要,可以选中或取消选中。无论如何,这不会改变我的观点。我将在我们所有的项目中打开"检查算术溢出/下溢"!(高级构建设置(。
当需要性能时,我将简单地使用未经检查的块。