はじめに
プログラミングをしていると、「一意な値が欲しい」という場面によく遭遇しますよね。
例えば、ファイル名の重複を避けたい、データベースのIDを生成したい、セッション管理をしたいなど。
そんな時に便利なのが**UUID(またはGUID)**です。
f3cb719d-2931-4bfc-babc-866a4ce2d260
このように0~9, A~Fの16種類の文字32個をハイフンで連結したものです。
UUIDとは?GUIDとは?
UUID(ユーユーアイディー)
- 正式名称: Universally Unique Identifier(汎用一意識別子)
- 概要: 世界中で一意(重複しない)になるように設計された識別子
- 標準: RFC 4122で国際標準化
GUID(ジーユーアイディー)
- 正式名称: Globally Unique Identifier(グローバル一意識別子)
- 概要: MicrosoftによるUUIDの実装
- 関係: UUIDとGUIDはほぼ同じもの
どちらも、「世界中で重複しない番号」を作る仕組みです。
GUIDはMicrosoftによるUUIDの実装というだけで、UUIDとGUIDはほぼ同じ意味です。
C#ではGUIDを生成しますが、ややこしいのでUUIDということで話を進めていきます。
UUIDのバージョンによる生成方法の違い
UUIDには複数のバージョンがあり、それぞれ生成方法が異なります
UUID Version 1(時間ベース)
- 時刻: 1582年10月15日からの100ナノ秒単位
- MACアドレス: ネットワークインターフェースのMAC
- クロックシーケンス: カウンター値
- ノード: 通常はMACアドレス
UUID Version 2(DCEセキュリティ)
- Version 1 + POSIX UID/GID
- あまり使用されない
UUID Version 3(名前ベース MD5)
- 名前空間UUID + 名前 をMD5ハッシュ
- 決定的(同じ入力なら同じ結果)
UUID Version 4(ランダム)
- 128ビット中、122ビットがランダム
- 6ビットはバリアント情報(uuidがどの仕様で生成されたか)
- 最も一般的
UUID Version 5(名前ベース SHA-1)
- 名前空間UUID + 名前 をSHA-1ハッシュ
- 決定的(同じ入力なら同じ結果)
後でで紹介するuuidを生成するメソッドもVersion4が使用されています。
なぜ重複しないのか
UUID(GUID)の構造
UUIDは**128ビット(16バイト)**のデータで、文字列として表示すると
12345678-90ab-cdef-1234-123456789abc
- 文字数: 36文字(ハイフン込み)または32文字(ハイフンなし)
- 使用文字: 16進数の16種類(0-9, A-F)
ハイフンなし32文字中2文字はバリアント情報が使用されている。
バリアント = UUIDの「規格識別子」
一言で言うと
「このUUIDはどの仕様で作られたかを示すラベル」
4つの種類
- Apollo NCS (0-7) - 古い規格
- RFC 4122 (8-B) - 現在の標準 ← C#はこれ
- Microsoft (C-D) - Microsoft独自
- 予約済み (E-F) - 将来用
[ 8, 9, A, B ] の4通りが使用される。
# 32文字の内訳
例: 12345678-90ab-4def-8234-123456789abc
役割: RRRRRRRR-RRRR-4RRR-VRRR-RRRRRRRRRRRR
- R = 完全ランダム(30文字)
- 4 = バージョン固定(1文字)
- V = 上位2ビット固定 + 下位2ビットランダム(1文字)
16番目の文字の詳細
文字 | 2進数 | 上位2ビット | 下位2ビット |
---|---|---|---|
8 | 1000 | 10(固定) | 00(ランダム) |
9 | 1001 | 10(固定) | 01(ランダム) |
A | 1010 | 10(固定) | 10(ランダム) |
B | 1011 | 10(固定) | 11(ランダム) |
可能な組み合わせ:
16^30×4(ランダム値30文字とバリアント情報4種類)
約85澗(85かん)という天文学的な確率になります。
単位 | 冪乗 |
---|---|
万(まん) | 10^4 |
億(おく) | 10^8 |
兆(ちょう) | 10^12 |
京(けい) | 10^16 |
垓(がい) | 10^20 |
じょ | 10^24 |
穣(じょう) | 10^28 |
溝(こう) | 10^32 |
澗(かん) | 10^36 |
あくまでUUIDは一意性確保のためのツールであり、セキュリティ用途ではありません。
暗号化の用途で使用しないようにしましょう。
C#でのUUID作成方法
C#ではGuid
クラスを使ってUUIDを作成できます。
基本的な作成方法
using System;
class Program
{
static void Main()
{
// 新しいUUID(GUID)を生成
Guid uuid = Guid.NewGuid();
Console.WriteLine($"生成されたUUID: {uuid}");
// 出力例: 生成されたUUID: 12345678-1234-1234-1234-123456789abc
}
}
複数のUUIDを生成してみる
using System;
class Program
{
static void Main()
{
Console.WriteLine("5つのUUIDを生成してみます:");
for (int i = 1; i <= 5; i++)
{
Guid uuid = Guid.NewGuid();
Console.WriteLine($"{i}: {uuid}");
}
}
}
実行結果例:
5つのUUIDを生成してみます:
1: 4c0a1c48-8fd8-4502-b106-5dd648870ba2
2: be2d1341-94c7-4852-a2fa-e3082cbf586b
3: f3cb719d-2931-4bfc-babc-866a4ce2d260
4: 6531382c-8973-410e-9543-3f61b93af885
5: 6fdf7bb7-fcbc-4c39-a3ba-38f3d8216098
毎回異なる値が生成されることが分かります。
UUID(GUID)の文字列形式
UUIDを文字列として扱う場合、いくつかの形式があります。
using System;
class Program
{
static void Main()
{
Guid uuid = new Guid("12345678-1234-1234-1234-123456789abc");
Console.WriteLine("=== UUID文字列形式の種類 ===");
// D形式(デフォルト)- ハイフン区切り
Console.WriteLine($"D形式: {uuid:D}");
Console.WriteLine($"デフォルト: {uuid}");
// N形式 - ハイフンなし
Console.WriteLine($"N形式: {uuid:N}");
// B形式 - 波括弧付き
Console.WriteLine($"B形式: {uuid:B}");
// P形式 - 丸括弧付き
Console.WriteLine($"P形式: {uuid:P}");
// X形式 - 16進数配列形式
Console.WriteLine($"X形式: {uuid:X}");
// ToString()メソッドでの明示的指定
Console.WriteLine();
Console.WriteLine("ToString()メソッドでの指定:");
Console.WriteLine($"ToString(): {uuid.ToString()}");
Console.WriteLine($"ToString(\"D\"): {uuid.ToString("D")}");
Console.WriteLine($"ToString(\"N\"): {uuid.ToString("N")}");
Console.WriteLine($"ToString(\"B\"): {uuid.ToString("B")}");
Console.WriteLine($"ToString(\"P\"): {uuid.ToString("P")}");
Console.WriteLine($"ToString(\"X\"): {uuid.ToString("X")}");
}
}
実行結果:
=== UUID文字列形式の種類 ===
D形式: 12345678-1234-1234-1234-123456789abc
デフォルト: 12345678-1234-1234-1234-123456789abc
N形式: 123456781234123412341234567890abc
B形式: {12345678-1234-1234-1234-123456789abc}
P形式: (12345678-1234-1234-1234-123456789abc)
X形式: {0x12345678,0x1234,0x1234,{0x12,0x34,0x12,0x34,0x56,0x78,0x9a,0xbc}}
ToString(): 12345678-1234-1234-1234-123456789abc
ToString("D"): 12345678-1234-1234-1234-123456789abc
ToString("N"): 123456781234123412341234567890abc
ToString("B"): {12345678-1234-1234-1234-123456789abc}
ToString("P"): (12345678-1234-1234-1234-123456789abc)
ToString("X"): {0x12345678,0x1234,0x1234,{0x12,0x34,0x12,0x34,0x56,0x78,0x9a,0xbc}}
各形式の特徴
形式 | 文字数 | 特徴 |
---|---|---|
D | 36文字 | ハイフン区切り(デフォルト) |
N | 32文字 | ハイフンなし |
B | 38文字 | 波括弧 {} で囲む |
P | 38文字 | 丸括弧 () で囲む |
X | 68文字 | 16進数配列形式 |
使用例
ファイル名の重複回避
using System;
using System.IO;
class Program
{
static void Main()
{
string originalFileName = "report.pdf";
// ファイル名にUUIDを付加して重複を避ける
string uuid = Guid.NewGuid().ToString("N").Substring(0, 8); // 8文字に短縮
string uniqueFileName = $"report_{uuid}.pdf";
Console.WriteLine($"元のファイル名: {originalFileName}");
Console.WriteLine($"一意なファイル名: {uniqueFileName}");
// 実際のファイル作成例
string filePath = Path.Combine(@"C:\temp", uniqueFileName);
Console.WriteLine($"保存先: {filePath}");
}
}
実行結果例:
元のファイル名: report.pdf
一意なファイル名: report_a1b2c3d4.pdf
保存先: C:\temp\report_a1b2c3d4.pdf
8文字に短縮しても 16^8 = 約43億となるので8文字でも十分重複は防ぐことができそうです。
パフォーマンスは大丈夫?
uuidを100万回生成して時間を測ってみようと思います。
using System;
using System.Diagnostics;
class Program
{
static void Main()
{
const int count = 1000000; // 100万回
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
Guid uuid = Guid.NewGuid();
}
sw.Stop();
Console.WriteLine($"{count:N0}個のUUID生成時間: {sw.ElapsedMilliseconds}ms");
}
}
実行結果例(環境により異なります)
1,000,000個のUUID生成時間: 45ms
かなり高速に生成できることが分かりました。
まとめ
C#でのUUID作成はGuid.NewGuid()
で簡単にできます。
文字列化は用途に応じてToString()
の形式を選択
以上、UUIDについてまとめました。少しでも参考になれば幸いです。間違いなどあれば指摘いただけると嬉しいです。
参考情報
公式ドキュメント
- Microsoft Docs - Guid Struct
- Microsoft Docs - Guid.NewGuid Method
- Microsoft Docs - Guid.ToString Method