Создайте статическую переменную экземпляра и используйте Interlocked.Increment(ref nextId)
для нее.
class Robot {
static int nextId;
public int RobotId {get; private set;}
Robot() {
RobotId = Interlocked.Increment(ref nextId);
}
}
Примечание # 1: использование nextId++
будет допустимо только в непараллельных средах; Interlocked.Increment
работает, даже если вы выделяете своих роботов из нескольких потоков.
РЕДАКТИРОВАТЬ Это не касается повторного использования идентификаторов роботов. Если вам требуется повторное использование, решение будет намного более сложным: вам нужен список идентификаторов многократного использования и ReaderWriterLockSlim
вокруг кода, который обращается к этому списку.
class Robot : IDisposable {
static private int nextId;
static private ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
static private IList<int> reuseIds = new List<int>();
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();
}
}
Примечание # 2: Если вы хотите повторно использовать меньшие идентификаторы перед большими идентификаторами (в отличие от повторного использования идентификаторов, выпущенных ранее, до идентификаторов, выпущенных позже, как я их кодировал), вы можете заменить IList<int>
на SortedSet<int>
и внесите несколько корректировок в те части, где ID, который будет использоваться повторно, взят из коллекции.