سؤال

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.

هل كانت مفيدة؟

المحلول

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.

نصائح أخرى

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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top