如何在C#中的联锁增量之后检查溢出?

如何在C#中的联锁增量之后检查溢出?,c#,integer-overflow,interlocked,interlocked-increment,C#,Integer Overflow,Interlocked,Interlocked Increment,调用interlocated.Increment后检查溢出的正确方法是什么? 我有一个ID生成器,在程序执行期间生成唯一的ID,目前我测试它,增量返回零 public static class IdGenerator { private static int _counter = 0; public static uint GetNewId() { uint newId = (uint)System.Threading.Interlocked.Increment

调用
interlocated.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数量相当大,(在异常大的输入上,
\u计数器
可能会在递增时溢出,在这种情况下,我希望抛出一个例外(尽早崩溃以简化调试)

摘录自:

此方法通过包装处理溢出条件:if
location
=
Int32.MaxValue
location+1
=
Int32.MinValue
。没有抛出异常


只需检查
newId
是否为
Int32.MinValue
(在转换为
uint
之前)并抛出异常


从增量中获取
MinValue
的唯一方法是通过溢出。

考虑使用
未选中的

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键空间
  • 更简单、更小的代码

  • 如果两个线程在短时间内连续增加值会怎么样?@JeppeStigNielsen:那么其中一个线程将溢出,而另一个线程则不会。
    联锁的整个要点。增量
    是原子的;这不是问题。啊,当然,你告诉他检查
    增量
    的返回值,而不是
    \u计数器
    字段的实际值。那么,我同意你的看法。但是他应该摆脱对
    uint
    的转换,或者别的什么。@JeppeStigNielsen:
    newId
    Increment()
    的返回值。你说得对,没有问题。还有一件事:当他的代码出现在问题中时,他只是将32位有符号整数重新解释为无符号32位整数,并且他能够获得高达
    4'294'967'295
    的ID。因此,如果我们假设他没有使用
    /checked
    编译器选项构建代码,那么他的原始代码运行良好。如果他使用了你的答案,他只能生成(大概)他以前能得到的一半的ID。考虑使用<代码>长< /代码>。注意:<代码>(UIN)In。MimValue/Cult>投掷。@ Salk(你的最后一个注释)好,<代码>(UIN)In。MimValue/CODE >,因为文字不会编译。但是一个非常量变量或表达式
    int i=int.MinValue
    点击转换
    (uint)i
    ,将不会在通常的
    未选中的
    上下文中抛出。@SLaks谢谢,我没有想到,应该用
    未选中的
    (uint)int.MinValue>来包装该转换,如下所示:
    未选中((uint)int.MinValue)
    我想是吧。沉默的向下投票不会给社区带来任何好处。如果你认为asnwer是错误的/不完整的,即使你已经投了反对票,也要写下来,至少要解释一下你的立场。