调用Interlocked.Increment
后检查溢出的正确方法是什么
我有一个ID生成器,它在程序执行期间生成唯一的ID,目前我测试增量是否返回零。
public static class IdGenerator {
private static int _counter = 0;
public static uint GetNewId() {
uint newId = (uint)System.Threading.Interlocked.Increment(ref _counter);
if (newId == 0) {
throw new System.Exception("Whoops, ran out of identifiers");
}
return newId;
}
}
考虑到我每次运行生成的ID数量相当大,_counter
在递增时可能会溢出(在异常大的输入上),在这种情况下我想抛出一个异常(提前崩溃以便于调试)。
微软文档摘录:
此方法通过包装处理溢出条件:如果
location
=Int32.MaxValue
,则location + 1
=Int32.MinValue
。没有引发异常。
只需检查newId
是否为Int32.MinValue
(在转换为uint
之前)并引发异常。
从增量中获取MinValue
的唯一方法是通过溢出。
考虑使用unchecked
public static class IdGenerator
{
private static int _counter;
public static uint GetNewId()
{
uint newId = unchecked ((uint) System.Threading.Interlocked.Increment(ref _counter));
if (newId == 0)
{
throw new System.Exception("Whoops, ran out of identifiers");
}
return newId;
}
}
在这种情况下,你会得到
- 性能提升不大,因为编译器不会检查溢出
- x2个按键空间
- 更简单、更小的代码