'How do I check for overflow after an Interlocked.Increment in C#?

What is the correct way to check for an overflow after a call to Interlocked.Increment?

I have an ID generator that generates unique ids during the program's execution, and currently I test if the increment returned zero.

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;
    }
}

Given the rather large number of IDs that I generate per run, it is possibile (on an exceptionally large input) that the _counter will overflow when incremented, and I want to throw an exception in that case (crash early to ease debugging).

Excerpt from Microsoft's documentation:

This method handles an overflow condition by wrapping: if location = Int32.MaxValue, location + 1 = Int32.MinValue. No exception is thrown.



Solution 1:[1]

Just check whether newId is Int32.MinValue (before casting to uint) and throw an exception.

The only way to get MinValue from an increment is through overflow.

Solution 2:[2]

Consider using 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;
    }
}

In this case you get

  1. Little performance boost, because compiler won't check overflow.
  2. x2 space for keys
  3. Simpler and smaller code

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Alex Zhukovskiy