Как сгенерировать уникальные имена файлов в C #


131

Я реализовал алгоритм, который будет генерировать уникальные имена для файлов, которые будут сохраняться на жестком диске. Я добавляю DateTime: часы, минуты, секунды и миллисекунды, но все же он генерирует повторяющиеся имена файлов, потому что я загружаю несколько файлов за раз.

Как лучше всего сгенерировать уникальные имена для файлов, которые будут храниться на жестком диске, чтобы не было двух одинаковых файлов?


Это зависит от других требований; этот [старый] вопрос был / слишком расплывчатым.
— user2864740

Ответы:


241

Если удобочитаемость не имеет значения, используйте GUID .

Например:

var myUniqueFileName = string.Format(@"{0}.txt", Guid.NewGuid());

или короче :

var myUniqueFileName = $@"{Guid.NewGuid()}.txt";

В своих программах я иногда пытаюсь, например, 10 раз сгенерировать читаемое имя («Image1.png»… «Image10.png»), и если это не удается (поскольку файл уже существует), я возвращаюсь к GUID.

Обновить:

В последнее время я также использую DateTime.Now.Ticksвместо GUID:

var myUniqueFileName = string.Format(@"{0}.txt", DateTime.Now.Ticks);

или

var myUniqueFileName = $@"{DateTime.Now.Ticks}.txt";

Преимущество для меня в том, что это генерирует более короткое и «красивое» имя файла по сравнению с GUID.

Обратите внимание, что в некоторых случаях (например, при генерации большого количества случайных имен за очень короткое время) это может привести к неуникальным значениям.

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


7
Мне нравится использовать Ticks, поскольку GUID действительно уродлив. Вы также можете получить хеш Ticks, который уменьшает длину символа в имени файла. DateTime.Now.Ticks.GetHashCode().ToString("x").ToUpper()
— WillMcKill

4
«Тики» предсказуемы и небезопасны по отношению к потокам (поскольку одни и те же «тики» могут быть получены из нескольких потоков / процессов). Это делает его непригодным для генерации временных файлов. Создание X..1..N может быть подходящим для задач, стоящих перед пользователем (например, копирование в проводнике), но сомнительно для работы сервера.
— user2864740

90

использование

Path.GetTempFileName()

или используйте новый GUID ().

Path.GetTempFilename () в MSDN .


Вот ссылка на документ MSDN: msdn.microsoft.com/en-us/library/…
— epotter

3
Обратите внимание, что это GetTempFileName()может вызвать исключение, если вы создадите много таких файлов, не удаляя их.
— Joey

21
«Метод GetTempFileName вызовет исключение IOException, если он используется для создания более 65535 файлов без удаления предыдущих временных файлов». говорится в статье MSDN.
— ağdaş Tekin

1
ВНИМАНИЕ: GetTempFileNameбудет создавать файл. Это также означает, что он выбирает временный путь . С другой стороны, GetRandomFileNameподходит для создания имени файла формата 8.3, которое можно использовать с другим путем. (Я видел ужасный код, который использует GetTempFileName с File.Delete только для того, чтобы использовать имя файла в другом месте ..)
— user2864740,

77
System.IO.Path.GetRandomFileName()

Path.GetRandomFileName () в MSDN .


Вот ссылка на документ MSDN: msdn.microsoft.com/en-us/library/…
— epotter

13
@RyBolt: Поскольку вам не нужно засеивать себя, вам почти не о чем помнить при использовании этого метода. И я ожидаю, что подавляющее большинство разработчиков не имеют представления о том, как создавать безопасные криптографические системы.
— Joey

54

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

Например:

public string GenerateFileName(string context)
{
    return context + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + "_" + Guid.NewGuid().ToString("N");
}

filename1 = GenerateFileName("MeasurementData");
filename2 = GenerateFileName("Image");

Таким образом, когда я сортирую по имени файла, он автоматически группирует файлы по контекстной строке и сортирует по метке времени.

Обратите внимание, что ограничение имени файла в Windows составляет 255 символов.


1
+1 За предложение включить полезную информацию в сочетании с GUID. - Небольшое отступление: включение даты и времени в имя файла излишне, когда вы можете просто Right Click > Sort By > Date.
— Тимоти Шилдс

1
Время становится полезным, если вы храните в одном каталоге кучу файлов с разными контекстами. Конечно, создание имени файла должно быть скорректировано в зависимости от ваших конкретных потребностей.
— Mas

Должно быть Guid.NewGuid().ToString();. Отсутствуют скобки. +1 в противном случае
— Laurent W.

Это очень красиво. Отметка времени и Guid. +1
— JoshYates1980

Мне нравится это решение +1, я добавил второе расширение строки параметра, которое я добавляю к fileName, это дополнительно поддерживает идею контекста и позволяет легко открывать файл с помощью приложения по умолчанию двойным щелчком, если это необходимо
— shelbypereira

23

Вот алгоритм, который возвращает уникальное читаемое имя файла на основе предоставленного оригинала. Если исходный файл существует, он постепенно пытается добавить индекс к имени файла, пока не найдет тот, который не существует. Он считывает существующие имена файлов в HashSet для проверки на конфликты, поэтому это довольно быстро (несколько сотен имен файлов в секунду на моей машине), оно также является потокобезопасным и не страдает от состояния гонки.

Например, если вы его передадите test.txt, он попытается создать файлы в следующем порядке:

test.txt
test (2).txt
test (3).txt

и т.д. Вы можете указать максимальное количество попыток или оставить значение по умолчанию.

Вот полный пример:

class Program
{
    static FileStream CreateFileWithUniqueName(string folder, string fileName, 
        int maxAttempts = 1024)
    {
        // get filename base and extension
        var fileBase = Path.GetFileNameWithoutExtension(fileName);
        var ext = Path.GetExtension(fileName);
        // build hash set of filenames for performance
        var files = new HashSet<string>(Directory.GetFiles(folder));

        for (var index = 0; index < maxAttempts; index++)
        {
            // first try with the original filename, else try incrementally adding an index
            var name = (index == 0)
                ? fileName
                : String.Format("{0} ({1}){2}", fileBase, index, ext);

            // check if exists
            var fullPath = Path.Combine(folder, name);
            if(files.Contains(fullPath))
                continue;

            // try to create the file
            try
            {
                return new FileStream(fullPath, FileMode.CreateNew, FileAccess.Write);
            }
            catch (DirectoryNotFoundException) { throw; }
            catch (DriveNotFoundException) { throw; }
            catch (IOException) 
            {
                // Will occur if another thread created a file with this 
                // name since we created the HashSet. Ignore this and just
                // try with the next filename.
            } 
        }

        throw new Exception("Could not create unique filename in " + maxAttempts + " attempts");
    }

    static void Main(string[] args)
    {
        for (var i = 0; i < 500; i++)
        {
            using (var stream = CreateFileWithUniqueName(@"c:\temp\", "test.txt"))
            {
                Console.WriteLine("Created \"" + stream.Name + "\"");
            }
        }

        Console.ReadKey();
    }
}

потокобезопасный ? неstatic readonly переменная ниlock?
— Kiquenet

Сам метод статичен, поэтому ничего не разделяет, поэтому я считаю, что несколько потоков могут безопасно использовать этот метод одновременно. Возможно, потокобезопасность - не совсем правильный термин - я пытаюсь передать, что если другой поток / процесс создает файл с конфликтующим именем во время выполнения, этот метод восстанавливается и пробует следующее доступное имя. Не стесняйтесь редактировать, если считаете, что это можно улучшить.
— Майк Чемберлен

Возможно, «не страдаю от состояния гонки» - лучший способ выразить это.
— Майк Чемберлен

10

Я использую GetRandomFileName :

Метод GetRandomFileName возвращает криптографически стойкую случайную строку, которую можно использовать как имя папки или имя файла. В отличие от GetTempFileName, GetRandomFileName не создает файл. Когда безопасность вашей файловой системы имеет первостепенное значение, этот метод следует использовать вместо GetTempFileName.

Пример:

public static string GenerateFileName(string extension="")
{
    return string.Concat(Path.GetRandomFileName().Replace(".", ""),
        (!string.IsNullOrEmpty(extension)) ? (extension.StartsWith(".") ? extension : string.Concat(".", extension)) : "");
}

Всегда ли метод GetRandomFileName () каждый раз генерирует уникальное имя файла, подобное GUID ()?
— Ашиш Шукла

1
@AshishShukla вообще-то понятия не имею. msdn сообщает, что генерируется «криптостойкая случайная строка». Пока проблем не было. Если уникальность важна, дополнительная проверка может быть хорошей идеей.
— Koray

3
  1. Создайте имя файла с меткой времени в соответствии с обычным процессом
  2. Проверьте, существует ли имя файла
  3. False - сохранить файл
  4. True - добавить в файл дополнительный символ, возможно, счетчик
  5. Перейти к шагу 2

10
Этот алгоритм может быть использован для параллелизма,
— Джейдер Диас,

3

Вы можете автоматически создать уникальное имя файла без каких-либо специальных методов. Просто используйте следующее с классом StorageFolder или StorageFile . Ключ здесь: CreationCollisionOption.GenerateUniqueNameиNameCollisionOption.GenerateUniqueName

Чтобы создать новый файл с уникальным именем:

var myFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("myfile.txt", NameCollisionOption.GenerateUniqueName);

Чтобы скопировать файл в место с уникальным именем файла:

var myFile2 = await myFile1.CopyAsync(ApplicationData.Current.LocalFolder, myFile1.Name, NameCollisionOption.GenerateUniqueName);

Чтобы переместить файл с уникальным именем в место назначения:

await myFile.MoveAsync(ApplicationData.Current.LocalFolder, myFile.Name, NameCollisionOption.GenerateUniqueName);

Чтобы переименовать файл с уникальным именем в месте назначения:

await myFile.RenameAsync(myFile.Name, NameCollisionOption.GenerateUniqueName);

2

Я использую следующий код, и он отлично работает. Надеюсь, это может вам помочь.

Я начинаю с уникального имени файла, использующего временную метку -

"context_" + DateTime.Now.ToString ("ггггММддЧЧммссфффф")

Код C # -

public static string CreateUniqueFile(string logFilePath, string logFileName, string fileExt)
    {
        try
        {
            int fileNumber = 1;

            //prefix with . if not already provided
            fileExt = (!fileExt.StartsWith(".")) ? "." + fileExt : fileExt;

            //Generate new name
            while (File.Exists(Path.Combine(logFilePath, logFileName + "-" + fileNumber.ToString() + fileExt)))
                fileNumber++;

            //Create empty file, retry until one is created
            while (!CreateNewLogfile(logFilePath, logFileName + "-" + fileNumber.ToString() + fileExt))
                fileNumber++;

            return logFileName + "-" + fileNumber.ToString() + fileExt;
        }
        catch (Exception)
        {
            throw;
        }
    }

    private static bool CreateNewLogfile(string logFilePath, string logFile)
    {
        try
        {
            FileStream fs = new FileStream(Path.Combine(logFilePath, logFile), FileMode.CreateNew);
            fs.Close();
            return true;
        }
        catch (IOException)   //File exists, can not create new
        {
            return false;
        }
        catch (Exception)     //Exception occured
        {
            throw;
        }
    }

1

Вам нужна отметка даты и времени в имени файла?

Вы можете сделать имя файла GUID.


@downvoter Есть ли причина для голосования "против"? GUID для имени файла кажется популярным ответом на этот вопрос.
— Ларри Хипп

Это повторяющийся ответ, и у меня недостаточно репутации, чтобы проголосовать против
— Jader Dias

@XMLforDummies мой ответ был одним из первых. Может показаться, что это не так сейчас, потому что к настоящему времени это просто показывает часы. Это повторяющийся ответ, потому что это, вероятно, правильный ответ.
— Ларри Хипп


1

Как насчет использования Guid.NewGuid()для создания GUID и использования его в качестве имени файла (или части имени файла вместе с меткой времени, если хотите).


1

Я написал простую рекурсивную функцию, которая генерирует имена файлов, как это делает Windows, путем добавления порядкового номера перед расширением файла.

Если задан путь к желаемому файлу C:\MyDir\MyFile.txtи файл уже существует, он возвращает окончательный путь к файлу C:\MyDir\MyFile_1.txt.

Он называется так:

var desiredPath = @"C:\MyDir\MyFile.txt";
var finalPath = UniqueFileName(desiredPath);

private static string UniqueFileName(string path, int count = 0)
{
    if (count == 0)
    {
        if (!File.Exists(path))
        {
            return path;
        }
    }
    else
    {
        var candidatePath = string.Format(
            @"{0}\{1}_{2}{3}",
            Path.GetDirectoryName(path),
            Path.GetFileNameWithoutExtension(path),
            count,
            Path.GetExtension(path));

        if (!File.Exists(candidatePath))
        {
            return candidatePath;
        }
    }

    count++;
    return UniqueFileName(path, count);
}

Это не является потокобезопасным или технологическим. Существует условие гонки с проверкой File.Exists и любым (предполагаемым позднее) созданием файла. Проще говоря, при вызове дважды подряд без создания файла он вернет тот же результат.
— user2864740

1

Почему мы не можем создать уникальный идентификатор, как показано ниже.

Мы можем использовать DateTime.Now.Ticks и Guid.NewGuid (). ToString (), чтобы объединить их вместе и создать уникальный идентификатор.

По мере добавления DateTime.Now.Ticks мы можем узнать дату и время в секундах, в которые создается уникальный идентификатор.

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

var ticks = DateTime.Now.Ticks;
var guid = Guid.NewGuid().ToString();
var uniqueSessionId = ticks.ToString() +'-'+ guid; //guid created by combining ticks and guid

var datetime = new DateTime(ticks);//for checking purpose
var datetimenow = DateTime.Now;    //both these date times are different.

Мы даже можем взять часть тиков в уникальном идентификаторе и проверить дату и время позже для использования в будущем.

Вы можете прикрепить созданный уникальный идентификатор к имени файла или использовать его для создания уникального идентификатора сеанса для входа и выхода пользователей из нашего приложения или веб-сайта.


Зачем заморачиваться с "галочками", если есть GUID?
— user2864740

В любом сценарии, если вам нужно проверить, когда сгенерирован uniqueSessionId, вы получите точное время. И при этом конкретный тик будет происходить только один раз в жизни.
— Джиниш Увантавида

Тривиально это предположение о тиках неверно: 1) несколько наблюдателей могут видеть одну и ту же «галочку» (подумайте о потоках / процессах) и 2) одну и ту же «галочку» может несколько раз наблюдать один и тот же наблюдатель, если запрос выполняется достаточно быстро.
— user2864740

Однако, по только с использованием Guid.NewGuid (и игнорируя тот факт , что не является «криптографически случайным» , которые могут представлять интерес в некоторых случаях), мы можем утверждать , что при достаточно высокой вероятности того, что мы не заботимся о противном случае, уникальный идентификатор будет быть сгенерированным - это гораздо более высокая гарантия, чем «тики» . Таким образом, «галочки» здесь не имеют значения / использования, кроме как «вторичных» данных, вставленных в имя файла.
— user2864740

(FWIW: я только что исправил код со сломанным вышеупомянутым утверждением об «уникальном времени» ..)
— user2864740

0

Если вы хотите иметь дату, время, часы, минуты и т. Д., Вы можете использовать статическую переменную. Добавьте значение этой переменной к имени файла. Вы можете начать счетчик с 0 и увеличивать его после создания файла. Таким образом, имя файла обязательно будет уникальным, поскольку в файле также есть секунды.


0

Обычно я делаю что-то в этом роде:

  • начать с имени основного файла ( work.dat1например)
  • попробуйте создать его с помощью CreateNew
  • если это сработает, у вас есть файл, иначе ...
  • смешайте текущую дату / время с именем файла ( work.2011-01-15T112357.datнапример)
  • попробуйте создать файл
  • если это сработало, у вас есть файл, иначе ...
  • Добавьте монотонный счетчик в имя файла ( work.2011-01-15T112357.0001.datнапример. (Мне не нравятся GUID. Я предпочитаю порядок / предсказуемость).)
  • попробуйте создать файл. Продолжайте увеличивать счетчик и повторять попытки, пока файл не будет создан для вас.

Вот образец класса:

static class DirectoryInfoHelpers
{
    public static FileStream CreateFileWithUniqueName( this DirectoryInfo dir , string rootName )
    {
        FileStream fs = dir.TryCreateFile( rootName ) ; // try the simple name first

        // if that didn't work, try mixing in the date/time
        if ( fs == null )
        {
            string date = DateTime.Now.ToString( "yyyy-MM-ddTHHmmss" ) ;
            string stem = Path.GetFileNameWithoutExtension(rootName) ;
            string ext  = Path.GetExtension(rootName) ?? ".dat" ;

            ext = ext.Substring(1);

            string fn = string.Format( "{0}.{1}.{2}" , stem , date , ext ) ;
            fs = dir.TryCreateFile( fn ) ;

            // if mixing in the date/time didn't work, try a sequential search
            if ( fs == null )
            {
                int seq = 0 ;
                do
                {
                    fn = string.Format( "{0}.{1}.{2:0000}.{3}" , stem , date , ++seq , ext ) ;
                    fs = dir.TryCreateFile( fn ) ;
                } while ( fs == null ) ;
            }

        }

        return fs ;
    }

    private static FileStream TryCreateFile(this DirectoryInfo dir , string fileName )
    {
        FileStream fs = null ;
        try
        {
            string fqn = Path.Combine( dir.FullName , fileName ) ;

            fs = new FileStream( fqn , FileMode.CreateNew , FileAccess.ReadWrite , FileShare.None ) ;
        }
        catch ( Exception )
        {
            fs = null ;
        }
        return fs ;
    }

}

Возможно, вы захотите настроить алгоритм (например, всегда используйте все возможные компоненты для имени файла). Зависит от контекста - если бы я, например, создавал файлы журналов, которые, возможно, захотелось бы перевернуть, вы бы хотели, чтобы они все использовали один и тот же шаблон для имени.

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


0

Я заканчиваю объединение GUID со второй миллисекундной строкой день, месяц, год, и я думаю, что это решение неплохо для моего сценария


0

вы можете использовать Random.Next () также для генерации случайного числа. вы можете увидеть ссылку MSDN: http://msdn.microsoft.com/en-us/library/9b3ta19y.aspx


2
Я бы не рекомендовал это, поскольку это не обязательно должно быть случайным. Он должен быть уникальным.
— Макс

0

Я написал класс специально для этого. Он инициализируется «базовой» частью (по умолчанию используется метка времени с точностью до минуты), а после этого добавляются буквы для создания уникальных имен. Итак, если первый сгенерированный штамп - 1907101215a, второй - 1907101215b, затем 1907101215c и так далее.

Если мне нужно более 25 уникальных штампов, я использую унарные буквы z для подсчета 25. Итак, это 1907101215y, 1907101215za, 1907101215zb, ... 1907101215zy, 1907101215zza, 1907101215zzb и т. Д. Это гарантирует, что штампы всегда будут отсортированы в алфавитно-цифровом порядке в том порядке, в котором они были созданы (при условии, что следующий за штампом символ не является буквой).

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

/// <summary>
/// Class for generating unique stamps (for filenames, etc.)
/// </summary>
/// <remarks>
/// Each time ToString() is called, a unique stamp is generated.
/// Stamps are guaranteed to sort alphanumerically in order of generation.
/// </remarks>
public class StampGenerator
{
  /// <summary>
  /// All the characters which could be the last character in the stamp.
  /// </summary>
  private static readonly char[] _trailingChars =
  {
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
    'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
    'u', 'v', 'w', 'x', 'y'
  };

  /// <summary>
  /// How many valid trailing characters there are.
  /// </summary>
  /// <remarks>Should always equal _trailingChars.Length</remarks>
  public const int TRAILING_RANGE = 25;

  /// <summary>
  /// Maximum length of the stamp. Hard-coded for laziness.
  /// </summary>
  public const int MAX_LENGTH_STAMP = 28;

  /// <summary>
  /// Base portion of the stamp. Will be constant between calls.
  /// </summary>
  /// <remarks>
  /// This is intended to uniquely distinguish between instances.
  /// Default behavior is to generate a minute-accurate timestamp.
  /// </remarks>
  public string StampBase { get; }

  /// <summary>
  /// Number of times this instance has been called.
  /// </summary>
  public int CalledTimes { get; private set; }

  /// <summary>
  /// Maximum number of stamps that can be generated with a given base.
  /// </summary>
  public int MaxCalls { get; }

  /// <summary>
  /// Number of stamps remaining for this instance.
  /// </summary>
  public int RemainingCalls { get { return MaxCalls - CalledTimes; } }

  /// <summary>
  /// Instantiate a StampGenerator with a specific base.
  /// </summary>
  /// <param name="stampBase">Base of stamp.</param>
  /// <param name="calledTimes">
  /// Number of times this base has already been used.
  /// </param>
  public StampGenerator(string stampBase, int calledTimes = 0)
  {
    if (stampBase == null)
    {
      throw new ArgumentNullException("stampBase");
    }
    else if (Regex.IsMatch(stampBase, "[^a-zA-Z_0-9 \\-]"))
    {
      throw new ArgumentException("Invalid characters in Stamp Base.",
                                  "stampBase");
    }
    else if (stampBase.Length >= MAX_LENGTH_STAMP - 1)
    {
      throw new ArgumentException(
        string.Format("Stamp Base too long. (Length {0} out of {1})",
                      stampBase.Length, MAX_LENGTH_STAMP - 1), "stampBase");
    }
    else if (calledTimes < 0)
    {
      throw new ArgumentOutOfRangeException(
        "calledTimes", calledTimes, "calledTimes cannot be negative.");
    }
    else
    {
      int maxCalls = TRAILING_RANGE * (MAX_LENGTH_STAMP - stampBase.Length);
      if (calledTimes >= maxCalls)
      {
        throw new ArgumentOutOfRangeException(
          "calledTimes", calledTimes, string.Format(
            "Called Times too large; max for stem of length {0} is {1}.",
            stampBase.Length, maxCalls));
      }
      else
      {
        StampBase = stampBase;
        CalledTimes = calledTimes;
        MaxCalls = maxCalls;
      }
    }
  }

  /// <summary>
  /// Instantiate a StampGenerator with default base string based on time.
  /// </summary>
  public StampGenerator() : this(DateTime.Now.ToString("yMMddHHmm")) { }

  /// <summary>
  /// Generate a unique stamp.
  /// </summary>
  /// <remarks>
  /// Stamp values are orered like this:
  /// a, b, ... x, y, za, zb, ... zx, zy, zza, zzb, ...
  /// </remarks>
  /// <returns>A unique stamp.</returns>
  public override string ToString()
  {
    int zCount = CalledTimes / TRAILING_RANGE;
    int trailing = CalledTimes % TRAILING_RANGE;
    int length = StampBase.Length + zCount + 1;

    if (length > MAX_LENGTH_STAMP)
    {
      throw new InvalidOperationException(
        "Stamp length overflown! Cannot generate new stamps.");
    }
    else
    {
      CalledTimes = CalledTimes + 1;
      var builder = new StringBuilder(StampBase, length);
      builder.Append('z', zCount);
      builder.Append(_trailingChars[trailing]);
      return builder.ToString();
    }
  }
}

-1

DateTime.Now.Ticksнебезопасно, Guid.NewGuid()слишком некрасиво, если вам нужно что-то чистое и почти безопасное ( это не на 100% безопасно, например, если вы вызываете его 1000000 раз за 1 мс ), попробуйте:

Math.Abs(Guid.NewGuid().GetHashCode())

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


Есть ли проблема с моим голосовавшим за решение? пожалуйста, дай мне знать.
— Мехди Дехгани

Этот GetHashCodeметод возвращает int32-битный диапазон, тогда как a GUIDимеет 128-битный диапазон, поэтому вероятность его уникальности гораздо выше. Если вам не нравится формат GUIDзначения, просто вызовите ToString("N")его, и дефисы будут удалены.
— 4thex
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.