Перейти к основному содержимому

Guid в C# — шпаргалка

Разработчику

Контекст: идентификаторы и UUID/GUID · работа с типами · глоссарий — GUID


Зачем нужен Guid

GUID (Globally Unique Identifier) и UUID (Universally Unique Identifier) — одно и то же по смыслу: 128-битный идентификатор, который можно выдать объекту без общего счётчика в базе. В .NET тип называется System.Guid.

Типичные применения:

  • первичный ключ сущности в БД (uniqueidentifier в SQL Server, uuid в PostgreSQL);
  • correlation id в логах и трассировке;
  • имя файла или папки во временном хранилище;
  • ключ идемпотентности HTTP-запроса (Idempotency-Key).

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


Тип Guid в C#

Guidзначимый тип (struct), 16 байт (128 бит). Хранится по значению, как int или DateTime.

Guid id = Guid.NewGuid();
Guid? optional = null; // nullable для необязательных полей
Связь с UUID

Строка вида d3c1f20a-9b1f-4cf5-9f30-2d2389d61a44 — стандартное представление UUID по RFC 4122. В .NET Guid.NewGuid() создаёт идентификатор версии 4 (случайные биты). В .NET 9+ для сортируемых по времени ключей есть Guid.CreateVersion7().


Сводка методов и членов

ЧленВидНазначение
Guid.NewGuid()статический методСгенерировать новый уникальный идентификатор
Guid.Parse(string)статический методРазобрать строку в Guid; при ошибке — исключение
Guid.TryParse(string, out Guid)статический методБезопасный разбор; true/false без исключения
Guid.TryParseExact(...)статический методРазбор с учётом формата (N, D, B, P, X)
guid.ToString() / ToString(format)метод экземпляраСтроковое представление
guid.Equals(other)метод экземпляраСравнение на равенство
guid == otherоператорТо же сравнение для двух Guid
Guid.Emptyстатическое поле«Нулевой» GUID — все байты 0
guid.CompareTo(other)метод экземпляраПорядок для сортировки: -1, 0, 1

NewGuid() — генерация

Генерирует новый идентификатор. Подходит для первичных ключей, токенов корреляции, уникальных имён файлов.

Guid id = Guid.NewGuid();
string forHeader = id.ToString(); // формат по умолчанию (D)

В ASP.NET Core и EF Core поле Guid Id часто заполняют на клиенте или в доменной модели до SaveChanges:

public class Order
{
public Guid Id { get; init; } = Guid.NewGuid();
}

Для секретов (сессии, reset-токены, API keys) предпочтительнее RandomNumberGenerator или Convert.ToBase64String с достаточной длиной. Guid удобен для идентификации записей, но не заменяет отдельный дизайн криптостойких токенов.


Parse() и TryParse()

Parse — когда формат гарантирован

Преобразует строку в Guid. При неверном формате выбрасывает FormatException.

Guid id = Guid.Parse("d3c1f20a-9b1f-4cf5-9f30-2d2389d61a44");

Используйте после валидации контракта (внутренний сервис, миграция с известным набором строк).

TryParse — ввод пользователя и внешние API

Безопасный разбор без исключений:

if (!Guid.TryParse(input, out Guid id))
{
return BadRequest("Некорректный идентификатор");
}

Тот же подход, что для int.TryParse и DateTime.TryParse — см. преобразование типов.

TryParseExact — жёсткий формат

Если API отдаёт GUID без дефисов (N) или в фигурных скобках (B):

bool ok = Guid.TryParseExact(
hex32,
"N",
out Guid id);

ToString() — форматы строки

По умолчанию ToString() даёт формат D — с дефисами, без скобок:

d3c1f20a-9b1f-4cf5-9f30-2d2389d61a44

ФорматПример видаКогда использовать
Dxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxПо умолчанию, логи, JSON
N32 hex-символа без разделителейКомпактное хранение, URL без лишних символов
B{xxxxxxxx-xxxx-...}Совместимость со старыми API
P(xxxxxxxx-xxxx-...)Редко
X{0x...,0x...,...}Отладка, бинарное представление
string compact = id.ToString("N");
string defaultFormat = id.ToString(); // то же, что "D"

В маршрутах ASP.NET Core для параметра {id:guid} подходит стандартная строка формата D.


Equals(), == и Guid.Empty

Сравнение двух Guid на полное совпадение всех 128 бит:

bool equal = id1.Equals(id2);
bool same = id1 == id2;

Guid.Empty — константа 00000000-0000-0000-0000-000000000000. Удобна как «значение ещё не задано» в legacy-коде или DTO:

if (entity.Id == Guid.Empty)
{
entity.Id = Guid.NewGuid();
}

В новых проектах с nullable reference types чаще используют Guid? и проверку id is null, а не Empty.


CompareTo() — сортировка

Реализует IComparable<Guid>. Возвращает отрицательное число, ноль или положительное — как у строк и чисел:

int result = guid1.CompareTo(guid2);
// result < 0 → guid1 «меньше»
// result == 0 → равны
// result > 0 → guid1 «больше»

Порядок лексикографический по байтам, а не по времени создания. Для сортировки «как в БД по времени вставки» нужен отдельный столбец (CreatedAt) или UUID v7 (Guid.CreateVersion7() в .NET 9+).

var sorted = ids.OrderBy(g => g).ToList();

В базе данных и JSON

СУБД / контекстТип / примечание
SQL Serveruniqueidentifier (16 байт)
PostgreSQLuuid
SQLiteчасто TEXT с Guid.ToString()
System.Text.Jsonсериализует Guid как строку в кавычках

Именование внешних ключей в моделях данных — CustomerId или CustomerGuid — см. основы БД — именование FK.


Мини-чеклист

ЗадачаЧто выбрать
Новый ключ сущностиGuid.NewGuid()
Строка из API или формыGuid.TryParse
Компактная запись в URLToString("N")
Проверка «не инициализирован»Guid.Empty или Guid?
Сортировка по времени созданияDateTime / UUID v7, не CompareTo случайного v4

Типичные ошибки

ОшибкаПоследствиеЧто делать
Guid.Parse на пользовательском вводеFormatException в runtimeTryParse + сообщение об ошибке
Путать Empty и null для Guid?логика «не задано» работает не такявная модель: Guid? или Empty, не оба сразу
Ожидать хронологический порядок у NewGuid()v4 не упорядочен по времениCreatedAt или UUID v7
Использовать GUID как пароль или секретпредсказуемость не та же, что у спец. токенаRandomNumberGenerator, отдельная длина и хранение

Смежные материалы

Официальная документация: структура Guid, Guid.NewGuid.

См. также

Другие статьи этого же раздела в боковом меню (как на странице "О разделе").