Это неправильный ответ c, но он может дать вам идентификатор только с 11 символами.
В C# значение long
имеет 64 бита, которые, если закодированы с Base64, будут 12 символов, включая 1 отступ =
. Если мы обрежем отступ =
, будет 11 символов.
Одна из сумасшедших идей здесь заключается в том, что мы можем использовать комбинацию Unix Epoch и счетчик для одного значения эпохи, чтобы сформировать значение long
, Unix Epoch в C# DateTimeOffset.ToUnixEpochMilliseconds
имеет формат long
, но первые 2 байта из 8 байтов всегда равны 0, поскольку в противном случае значение времени даты будет больше, чем максимальное значение времени даты. Таким образом, это дает нам 2 байта для размещения счетчика ushort
.
Таким образом, всего, пока число генерации идентификатора не превышает 65536 в миллисекунду, мы можем иметь уникальный идентификатор:
// This is the counter for current epoch. Counter should reset in next millisecond
ushort currentCounter = 123;
var epoch = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
// Because epoch is 64bit long, so we should have 8 bytes
var epochBytes = BitConverter.GetBytes(epoch);
if (BitConverter.IsLittleEndian)
{
// Use big endian
epochBytes = epochBytes.Reverse().ToArray();
}
// The first two bytes are always 0, because if not, the DateTime.UtcNow is greater
// than DateTime.Max, which is not possible
var counterBytes = BitConverter.GetBytes(currentCounter);
if (BitConverter.IsLittleEndian)
{
// Use big endian
counterBytes = counterBytes.Reverse().ToArray();
}
// Copy counter bytes to the first 2 bytes of the epoch bytes
Array.Copy(counterBytes, 0, epochBytes, 0, 2);
// Encode the byte array and trim padding '='
var shortUid = Convert.ToBase64String(epochBytes).TrimEnd('=');