Альтернативная техника генерации уникальных идентификаторов - PullRequest
2 голосов
/ 24 февраля 2009

В приложении, когда создаются особые типы объектов, мне нужно сгенерировать уникальный идентификатор для каждого из них. Объекты создаются на фабрике и имеют высокую вероятность создания в массовых операциях. Я понимаю, что «Случайный» из фреймворка не так уж и «случайный», поэтому я попытался добавить метку времени следующим образом:

private string GenerateUniqueId()
{
    Random randomValue = new Random();
    return DateTime.Now.Ticks.ToString() + randomValue.Next().ToString();
}

К сожалению, даже это не работает. Для объектов, которые создаются в быстрой последовательности, я генерирую тот же уникальный идентификатор: - (

В настоящее время я реализую это в общих чертах следующим образом:

private string GenerateUniqueId()
{
    Random randomValue = new Random();
    int value = randomValue.Next();
    Debug.WriteLine(value.ToString());
    Thread.Sleep(100);
    return DateTime.Now.Ticks.ToString() + value.ToString();
}

Поскольку это не очень большое приложение, я думаю, что вместо реализации сложного алгоритма будет достаточно простого и быстрого метода.

Пожалуйста, предложите.

Ответы [ 5 ]

11 голосов
/ 24 февраля 2009

A GUID , вероятно, то, что вы ищете:

private string GenerateUniqueId()
{
    return Guid.NewGuid().ToString("N");
}

Если вы хотите меньший, более управляемый идентификатор, вы можете использовать что-то вроде этого:

private string GenerateUniqueId()
{
    using (var rng = new RNGCryptoServiceProvider())
    {
        // change the size of the array depending on your requirements
        var rndBytes = new byte[8];
        rng.GetBytes(rndBytes);
        return BitConverter.ToString(rndBytes).Replace("-", "");
    }
}

Примечание. Это даст вам только 64-битное число по сравнению со 128-битным GUID, так что вероятность коллизии будет выше. Вероятно, не проблема в реальном мире, хотя. Если это проблема, вы можете увеличить размер массива byte, чтобы увеличить идентификатор.

1 голос
/ 24 февраля 2009

В ваших комментариях Кодекса вы говорите, используйте уникальный идентификатор в качестве имени файла. Существует специальная функция для генерации криптографически безопасных имен файлов, Path.GetRandomFileName ()

Поскольку это криптографически безопасно, они будут уникальными даже в пакетных операциях. Формат немного ужасен, так как они оптимизированы для имен файлов, но он может работать и для других ссылок.

1 голос
/ 24 февраля 2009

Если вы не хотите указывать GUID, опция First будет статическим полем и будет заблокирована:

private static long lastId = 0
private static long GetNextId() {
  return Interlocked.Increment(ref lastId);
}

Если вы хотите что-то, основанное на временных тиках, запомните последнее значение и, если то же самое, вручную увеличьте и сохраните; в противном случае просто сохраните:

private static long lastTick = 0;
private static object idGenLock = new Object();
private static long GetNextId() {
  lock (idGenLock) {
    long tick = DateTime.UtcNow.Ticks;
    if (lastTick == tick) {
      tick = lastTick+1;
    }
    lastTick = tick;
    return tick;
  }
}

(Ни один из этих подходов не подходит для нескольких процессов.)

0 голосов
/ 24 февраля 2009

Если вы собираетесь прибегнуть к кодированию собственного UUID-генератора, убедитесь, что вы солите генератор.

Я предлагаю вам ознакомиться с пакетом с открытым исходным кодом ossp-uuid , который представляет собой API-интерфейс ISO-C и CLI для генерации универсально уникальных идентификаторов.

0 голосов
/ 24 февраля 2009

Почему ваша фабрика (предположительно однопоточная) не может генерировать последовательные уникальные целые числа? Если вы ожидали, что Random () сработает, почему бы не Guid () (или что-то подобное)?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...