C# Class Auto increment ID

前端 未结 6 1357
别那么骄傲
别那么骄傲 2021-02-03 12:05

I am creating a class in C# called \"Robot\", and each robot requires a unique ID property which gives themselves an identity.

Is there any way of creating an auto incr

6条回答
  •  臣服心动
    2021-02-03 12:38

    Create a static instance variable, and use Interlocked.Increment(ref nextId) on it.

    class Robot {
        static int nextId;
        public int RobotId {get; private set;}
        Robot() {
            RobotId = Interlocked.Increment(ref nextId);
        }
    }
    

    Note #1: using nextId++ would be valid only in non-concurrent environments; Interlocked.Increment works even if you allocate your robots from multiple threads.

    EDIT This does not deal with re-using robot IDs. If you need reuse, the solution is a lot more complex: you need a list of reusable IDs, and a ReaderWriterLockSlim around the code that accesses that list.

    class Robot : IDisposable {
        static private int nextId;
        static private ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
        static private IList reuseIds = new List();
        public int RobotId {get; private set;}
        Robot() {
            rwLock.EnterReadLock();
            try {
                if (reuseIds.Count == 0) {
                    RobotId = Interlocked.Increment(ref nextId);
                    return;
                }
            } finally {
                rwLock.ExitReadLock();
            }
            rwLock.EnterWriteLock();
            try {
                // Check the count again, because we've released and re-obtained the lock
                if (reuseIds.Count != 0) {
                    RobotId = reuseIds[0];
                    reuseIds.RemoveAt(0);
                    return;
                }
                RobotId = Interlocked.Increment(ref nextId);
            } finally {
                rwLock.ExitWriteLock();
            }
        }
        void Dispose() {
            rwLock.EnterWriteLock();
            reuseIds.Add(RobotId);
            rwLock.ExitWriteLock();
        }
    }
    

    Note #2: If you would like to reuse smaller IDs ahead of larger IDs (as opposed to reusing IDs released earlier before IDs released later, as I coded it) you can replace IList with SortedSet and make a few adjustments around the parts where an ID to be reused is taken from the collection.

提交回复
热议问题