C#で16進数と10進数を相互変換する方法|Convert.ToInt32・ToStringの使い方を解説

はじめに

C#で「16進数を10進数に変換したい」「10進数を16進数の文字列として表示したい」という場面は、意外と多くあります。たとえば、カラーコード、バイト列、通信データ、メモリアドレス、デバッグログ、ID管理などでは、10進数よりも16進数のほうが見やすいことがあります。

C#で16進数と10進数を相互変換する基本は、次の2つです。

C#
// 16進数の文字列 → 10進数の数値
int number = Convert.ToInt32("FF", 16);

// 10進数の数値 → 16進数の文字列
string hex = number.ToString("X");

Convert.ToInt32を使うと、16進数の文字列をint型の10進数として扱えます。一方、ToString("X")を使うと、10進数の数値を16進数表記の文字列に変換できます。Convert.ToInt32(String, Int32)の第2引数には基数を指定でき、指定できる基数は2、8、10、16です。

この記事では、C#で16進数と10進数を変換する方法を、基本から実務で使えるサンプルまで解説します。

1. C#で16進数と10進数を変換する基本

1-1. 16進数と10進数の違い

10進数は、普段の生活でよく使う数値表記です。0から9までの10個の数字を使って数を表します。

一方、16進数は0から9に加えて、AからFまでの文字を使います。16進数では、10進数の10から15を次のように表します。

10進数16進数
10A
11B
12C
13D
14E
15F
1610
255FF

たとえば、10進数の255は16進数ではFFです。C#で16進数と10進数を変換するときは、この「表記の違い」を意識することが大切です。

1-2. C#で扱う数値と文字列の関係

C#では、intlongなどの数値型は、内部的には数値として扱われます。画面に表示するときに「10進数で表示するか」「16進数で表示するか」を決めているだけです。

たとえば、次のnumberは数値としては同じ値です。

C#
int number = 255;

この255を10進数として表示すれば255、16進数として表示すればFFになります。

C#
int number = 255;

Console.WriteLine(number); // 255
Console.WriteLine(number.ToString("X")); // FF

つまり、10進数から16進数への変換は「数値を文字列としてどう表示するか」という処理です。反対に、16進数から10進数への変換は「16進数表記の文字列を数値として解釈する」処理です。

1-3. 変換でよく使うメソッドの全体像

C#で16進数と10進数を変換するときによく使うメソッドは、主に次のとおりです。

目的よく使う方法
16進数文字列を10進数の数値に変換Convert.ToInt32(hex, 16)"FF"255
10進数の数値を16進数文字列に変換number.ToString("X")255"FF"
16進数文字列をParseで変換int.Parse(hex, NumberStyles.HexNumber)"FF"255
失敗しても例外を出さずに変換int.TryParse(...)成功時だけ値を取得
10進数を2進数・8進数・16進数に変換Convert.ToString(number, base)255"ff"

まず覚えるべき基本形は、次の2つです。

C#
int decimalValue = Convert.ToInt32("FF", 16);
string hexValue = decimalValue.ToString("X");

2. 16進数の文字列を10進数の数値に変換する方法

2-1. Convert.ToInt32を使った基本的な変換

16進数の文字列を10進数の数値に変換するには、Convert.ToInt32を使います。

C#
string hex = "FF";

int number = Convert.ToInt32(hex, 16);

Console.WriteLine(number); // 255

"FF"は16進数で、10進数にすると255です。Convert.ToInt32(hex, 16)と書くことで、文字列hexを16進数として解釈し、int型の数値に変換できます。

2-2. Convert.ToInt32の第2引数に16を指定する理由

Convert.ToInt32の第2引数は、変換元の文字列が何進数で書かれているかを指定するためのものです。

C#
Convert.ToInt32("FF", 16);

この16は「文字列"FF"を16進数として読んでください」という意味です。もし第2引数を指定せずにConvert.ToInt32("FF")と書くと、C#は通常の10進数として解釈しようとします。しかし、10進数にはFという数字は存在しないため、変換できません。

C#
// これはエラーになる
int number = Convert.ToInt32("FF");

16進数の文字列を変換するときは、第2引数に16を指定するのが基本です。Convert.ToInt32(String, Int32)では、基数として2、8、10、16を指定できます。

2-3. 「0x」付きの16進数文字列を変換する方法

C#や多くのプログラミング言語では、16進数を表すときに0xを付けることがあります。

C#
int value = 0xFF;

文字列として"0xFF"を持っている場合も、Convert.ToInt32なら次のように変換できます。

C#
string hex = "0xFF";

int number = Convert.ToInt32(hex, 16);

Console.WriteLine(number); // 255

Convert.ToInt32で第2引数に16を指定した場合、文字列の先頭に0xまたは0Xを付けることができます。

ただし、後述するint.ParseNumberStyles.HexNumberを使う方法では、0x付きの文字列をそのまま変換できません。その場合は、先に0xを取り除いてから変換します。

C#
string input = "0xFF";

if (input.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
{
input = input.Substring(2);
}

int number = Convert.ToInt32(input, 16);

Console.WriteLine(number); // 255

2-4. 小文字・大文字の16進数は変換できるのか

16進数のAからFは、大文字でも小文字でも変換できます。

C#
int value1 = Convert.ToInt32("FF", 16);
int value2 = Convert.ToInt32("ff", 16);
int value3 = Convert.ToInt32("Ff", 16);

Console.WriteLine(value1); // 255
Console.WriteLine(value2); // 255
Console.WriteLine(value3); // 255

"FF""ff""Ff"はいずれも同じ値として解釈されます。見た目を統一したい場合は、入力時にToUpper()ToLower()でそろえることもできます。

C#
string hex = "ff";
hex = hex.ToUpper();

int number = Convert.ToInt32(hex, 16);

Console.WriteLine(hex); // FF
Console.WriteLine(number); // 255

2-5. 変換結果をConsole.WriteLineで確認するサンプルコード

実際にいくつかの16進数文字列を10進数に変換して確認してみましょう。

C#
string[] hexValues = { "0A", "10", "1F", "7F", "FF", "0x100" };

foreach (string hex in hexValues)
{
int number = Convert.ToInt32(hex, 16);
Console.WriteLine($"{hex} = {number}");
}

実行結果は次のようになります。

0A = 10
10 = 16
1F = 31
7F = 127
FF = 255
0x100 = 256

16進数の10は、10進数では16です。文字列としては同じ"10"に見えても、何進数として解釈するかによって値が変わる点に注意しましょう。

3. 10進数の数値を16進数の文字列に変換する方法

3-1. ToString("X")を使った基本的な変換

10進数の数値を16進数の文字列に変換するには、ToString("X")を使います。

C#
int number = 255;

string hex = number.ToString("X");

Console.WriteLine(hex); // FF

"X"は16進数表記を指定する標準の数値書式指定子です。C#の整数型に対してToString("X")を使うと、数値を16進数の文字列に変換できます。"X"または"x"の16進数書式指定子は整数型でサポートされ、結果は16進数の文字列になります。

3-2. ToString("x")とToString("X")の違い

ToString("X")ToString("x")の違いは、16進数のアルファベット部分を大文字にするか小文字にするかです。

C#
int number = 255;

Console.WriteLine(number.ToString("X")); // FF
Console.WriteLine(number.ToString("x")); // ff

"X"を指定するとAからFが大文字になります。"x"を指定すると小文字になります。標準の数値書式指定文字列では、書式指定子の大文字・小文字によって、9より大きい16進数の文字を大文字にするか小文字にするかが決まります。

ログや仕様書で大文字表記が求められる場合は"X"、URLや内部処理で小文字に統一したい場合は"x"を使うとよいでしょう。

3-3. 桁数をそろえてゼロ埋めする方法

16進数の桁数をそろえたい場合は、"X2""X4"のように桁数を指定します。

C#
int value1 = 10;
int value2 = 255;
int value3 = 4095;

Console.WriteLine(value1.ToString("X2")); // 0A
Console.WriteLine(value2.ToString("X2")); // FF
Console.WriteLine(value3.ToString("X4")); // 0FFF

"X2"は最低2桁、"X4"は最低4桁で表示するという意味です。桁数が足りない場合は、左側に0が追加されます。

C#
int number = 255;

Console.WriteLine(number.ToString("X2")); // FF
Console.WriteLine(number.ToString("X4")); // 00FF
Console.WriteLine(number.ToString("X8")); // 000000FF

16進数書式指定子では、精度指定子を使うことで結果文字列に必要な最小桁数を指定でき、必要に応じて左側がゼロ埋めされます。

3-4. 変換結果に「0x」を付けて表示する方法

ToString("X")だけでは、結果に0xは付きません。

C#
int number = 255;

Console.WriteLine(number.ToString("X")); // FF

0xFFのように表示したい場合は、文字列結合や文字列補間を使います。

C#
int number = 255;

string hex = "0x" + number.ToString("X");

Console.WriteLine(hex); // 0xFF

文字列補間を使うと、より読みやすく書けます。

C#
int number = 255;

string hex = $"0x{number:X}";

Console.WriteLine(hex); // 0xFF

桁数をそろえたい場合は、次のように書けます。

C#
int number = 255;

string hex = $"0x{number:X4}";

Console.WriteLine(hex); // 0x00FF

3-5. int・longなど数値型ごとの変換例

ToString("X")は、intだけでなく、byteshortlonguintulongなどの整数型で使えます。

C#
byte byteValue = 255;
int intValue = 255;
long longValue = 1234567890L;
uint uintValue = 4294967295;

Console.WriteLine(byteValue.ToString("X2")); // FF
Console.WriteLine(intValue.ToString("X")); // FF
Console.WriteLine(longValue.ToString("X")); // 499602D2
Console.WriteLine(uintValue.ToString("X")); // FFFFFFFF

扱う値がintの範囲に収まるならintで十分です。大きな値を扱う場合はlong、符号なしの32ビット値を扱いたい場合はuintを使います。

4. Convert.ToInt32以外で16進数を10進数に変換する方法

4-1. int.Parseを使って変換する方法

Convert.ToInt32以外にも、int.Parseを使って16進数文字列を10進数に変換できます。ただし、16進数として解釈するにはNumberStyles.HexNumberを指定します。

C#
using System;
using System.Globalization;

string hex = "FF";

int number = int.Parse(hex, NumberStyles.HexNumber);

Console.WriteLine(number); // 255

ParseTryParseは文字列を数値型に変換するための基本的な方法で、Parseは変換に失敗すると例外をスローし、TryParseは失敗時にfalseを返します。

4-2. NumberStyles.HexNumberを指定する方法

NumberStyles.HexNumberは、文字列を16進数として解釈するための指定です。

C#
using System.Globalization;

string hex = "1A";

int number = int.Parse(hex, NumberStyles.HexNumber);

Console.WriteLine(number); // 26

NumberStyles.HexNumberは、先頭・末尾の空白を許可し、16進数として解釈するための複合スタイルです。NumberStyles.AllowHexSpecifierでは、0-9A-Fa-fが有効な16進数として扱われますが、0x&hのような接頭辞は使えません。

そのため、次のようなコードは失敗します。

C#
using System.Globalization;

string hex = "0xFF";

// これはFormatExceptionになる
int number = int.Parse(hex, NumberStyles.HexNumber);

int.Parseで処理する場合は、必要に応じて0xを取り除きましょう。

C#
using System.Globalization;

string hex = "0xFF";

if (hex.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
{
hex = hex.Substring(2);
}

int number = int.Parse(hex, NumberStyles.HexNumber);

Console.WriteLine(number); // 255

4-3. int.TryParseで安全に変換する方法

ユーザー入力や外部ファイルから読み込んだ値を変換する場合は、int.TryParseを使うと安全です。

C#
using System;
using System.Globalization;

string hex = "FF";

bool success = int.TryParse(
hex,
NumberStyles.HexNumber,
null,
out int number
);

if (success)
{
Console.WriteLine(number); // 255
}
else
{
Console.WriteLine("変換できませんでした。");
}

TryParseは変換に成功するとtrueを返し、変換後の値をout引数で受け取ります。失敗した場合はfalseを返すため、例外処理を書かずに入力チェックできます。Int32.TryParseは、変換が成功したかどうかを戻り値で示すメソッドです。

4-4. Convert.ToInt32・Parse・TryParseの使い分け

3つの方法は、用途によって使い分けるとよいです。

方法特徴向いている場面
Convert.ToInt32(hex, 16)書き方がシンプル。0x付きも扱える固定値や信頼できる入力
int.Parse(hex, NumberStyles.HexNumber)数値型の標準的な変換方法失敗時に例外で処理したい場合
int.TryParse(hex, NumberStyles.HexNumber, null, out value)失敗しても例外が出ないユーザー入力や外部データ

初心者がまず覚えるなら、16進数から10進数への変換はConvert.ToInt32(hex, 16)、10進数から16進数への変換はToString("X")で問題ありません。

実務では、入力値が正しいと保証できないケースが多いため、ユーザー入力にはTryParseを使うのがおすすめです。

4-5. 例外を避けたい場合の実装パターン

例外を避けて安全に16進数文字列を処理したい場合は、次のようにメソッド化しておくと便利です。

C#
using System;
using System.Globalization;

static bool TryParseHex(string input, out int result)
{
result = 0;

if (string.IsNullOrWhiteSpace(input))
{
return false;
}

input = input.Trim();

if (input.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
{
input = input.Substring(2);
}

return int.TryParse(
input,
NumberStyles.HexNumber,
null,
out result
);
}

string hex = "0xFF";

if (TryParseHex(hex, out int number))
{
Console.WriteLine(number); // 255
}
else
{
Console.WriteLine("16進数として変換できません。");
}

このように、null、空文字、0x付き、変換失敗をまとめて処理しておくと、実務のコードで使い回しやすくなります。

5. 変換時によくあるエラーと対処法

5-1. FormatExceptionが発生する原因

FormatExceptionは、文字列が指定した形式に合っていない場合に発生します。

C#
int number = Convert.ToInt32("GG", 16);

16進数で使える文字は、0-9A-Fa-fです。Gは16進数の文字ではないため、変換できません。

また、次のように10進数として変換しようとした場合もエラーになります。

C#
int number = Convert.ToInt32("FF");

Convert.ToInt32(String, Int32)では、指定した基数で有効ではない文字が含まれている場合にFormatExceptionが発生します。

対処法としては、変換前に入力値をチェックするか、TryParseを使います。

C#
using System.Globalization;

string input = "GG";

if (int.TryParse(input, NumberStyles.HexNumber, null, out int number))
{
Console.WriteLine(number);
}
else
{
Console.WriteLine("16進数として正しくありません。");
}

5-2. OverflowExceptionが発生する原因

OverflowExceptionは、変換後の値が型の範囲を超える場合に発生します。

C#
string hex = "100000000"; // intで扱うには大きすぎる場合がある

int number = Convert.ToInt32(hex, 16);

intは32ビット符号付き整数です。扱える範囲は、通常-2,147,483,648から2,147,483,647です。これを超える値を扱う可能性がある場合は、longulongを検討します。

C#
string hex = "100000000";

long number = Convert.ToInt64(hex, 16);

Console.WriteLine(number); // 4294967296

Convert.ToInt32(String, Int32)では、値がInt32.MinValueより小さい、またはInt32.MaxValueより大きい場合にOverflowExceptionが発生することがあります。

5-3. 変換できない文字が含まれている場合の対処

ユーザー入力には、余計な空白、#0x、全角文字などが含まれることがあります。

たとえば、カラーコードとして"#FF0000"が入力された場合、そのままでは変換できません。

C#
string color = "#FF0000";

// そのままでは変換できない
// int value = Convert.ToInt32(color, 16);

この場合は、変換前に不要な文字を取り除きます。

C#
string color = "#FF0000";

color = color.Trim();

if (color.StartsWith("#"))
{
color = color.Substring(1);
}

int value = Convert.ToInt32(color, 16);

Console.WriteLine(value); // 16711680

0x#などの記号は、使う変換方法によって扱いが異なります。実務では、変換前に入力形式を統一してから処理するのがおすすめです。

5-4. 値がintの範囲を超える場合の対処

16進数は桁数が少なく見えても、実際には大きな値を表していることがあります。

C#
string hex = "FFFFFFFF";

この値は、符号なし32ビット整数として見れば4294967295です。しかし、intは符号付き32ビット整数なので、扱いに注意が必要です。

符号なしの値として扱いたい場合は、uintを使います。

C#
using System.Globalization;

string hex = "FFFFFFFF";

uint value = uint.Parse(hex, NumberStyles.HexNumber);

Console.WriteLine(value); // 4294967295

さらに大きな値を扱う場合は、ulongSystem.Numerics.BigIntegerも候補になります。

C#
using System.Globalization;
using System.Numerics;

string hex = "FFFFFFFFFFFFFFFF";

BigInteger value = BigInteger.Parse(hex, NumberStyles.HexNumber);

Console.WriteLine(value);

5-5. nullや空文字を変換するときの注意点

nullや空文字の扱いも注意が必要です。

C#
string? value = null;

int number = Convert.ToInt32(value, 16);

Console.WriteLine(number); // 0

Convert.ToInt32(String, Int32)は、valuenullの場合に0を返します。

一方、空文字は変換できません。

C#
string value = "";

int number = Convert.ToInt32(value, 16);

空文字の場合は例外が発生します。そのため、実務では次のように事前チェックを行うと安全です。

C#
string? input = "";

if (string.IsNullOrWhiteSpace(input))
{
Console.WriteLine("入力値が空です。");
}
else
{
int number = Convert.ToInt32(input, 16);
Console.WriteLine(number);
}

6. 実務で使える16進数・10進数変換のサンプル

6-1. カラーコードを10進数に変換する例

WebやUI開発では、カラーコードを扱うことがあります。たとえば、#FF0000は赤色を表すカラーコードです。

C#
string colorCode = "#FF0000";

string hex = colorCode.Replace("#", "");

int colorValue = Convert.ToInt32(hex, 16);

Console.WriteLine(colorValue); // 16711680

RGBの各成分を分けて取得したい場合は、文字列を分割します。

C#
string colorCode = "#336699";
string hex = colorCode.Replace("#", "");

int red = Convert.ToInt32(hex.Substring(0, 2), 16);
int green = Convert.ToInt32(hex.Substring(2, 2), 16);
int blue = Convert.ToInt32(hex.Substring(4, 2), 16);

Console.WriteLine($"R={red}, G={green}, B={blue}");
// R=51, G=102, B=153

カラーコードでは、2桁の16進数が1つの色成分を表します。FFは10進数で255000です。

6-2. バイト値を16進数で表示する例

バイナリデータや通信データをログに出す場合、バイト値を16進数で表示すると見やすくなります。

C#
byte value = 10;

string hex = value.ToString("X2");

Console.WriteLine(hex); // 0A

byteは0から255までの値を持ちます。16進数では00からFFで表せるため、X2で2桁表示にすると扱いやすくなります。

複数のバイトを16進数で表示する例です。

C#
byte[] data = { 0x01, 0x0A, 0x10, 0xFF };

foreach (byte b in data)
{
Console.Write($"{b:X2} ");
}

// 01 0A 10 FF

6-3. 配列やループで複数の値を変換する例

複数の10進数を16進数に変換したい場合は、配列とループを使います。

C#
int[] numbers = { 10, 15, 16, 31, 255, 256 };

foreach (int number in numbers)
{
Console.WriteLine($"{number} => {number:X}");
}

実行結果は次のようになります。

10 => A
15 => F
16 => 10
31 => 1F
255 => FF
256 => 100

反対に、複数の16進数文字列を10進数に変換する場合は次のように書けます。

C#
string[] hexValues = { "0A", "0F", "10", "1F", "FF", "100" };

foreach (string hex in hexValues)
{
int number = Convert.ToInt32(hex, 16);
Console.WriteLine($"{hex} => {number}");
}

6-4. デバッグログで16進数表示を使う例

フラグ値やビット演算の結果を確認するときは、10進数より16進数のほうがわかりやすいことがあります。

C#
int flags = 0b_0001_0010_1111_0000;

Console.WriteLine($"DEC: {flags}");
Console.WriteLine($"HEX: 0x{flags:X4}");

実行結果の例です。

DEC: 4848
HEX: 0x12F0

ビットマスクや通信プロトコルの値を確認するときは、0x{value:X}の形式でログ出力しておくと、仕様書の表記と照合しやすくなります。

C#
int command = 0xA5;

Console.WriteLine($"Command Code = 0x{command:X2}");
// Command Code = 0xA5

6-5. ユーザー入力された16進数を安全に処理する例

ユーザーが入力した値は、必ずしも正しい16進数とは限りません。そのため、TryParseを使って安全に処理しましょう。

C#
using System;
using System.Globalization;

Console.Write("16進数を入力してください: ");
string? input = Console.ReadLine();

if (string.IsNullOrWhiteSpace(input))
{
Console.WriteLine("入力値が空です。");
return;
}

input = input.Trim();

if (input.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
{
input = input.Substring(2);
}

if (int.TryParse(input, NumberStyles.HexNumber, null, out int number))
{
Console.WriteLine($"10進数: {number}");
Console.WriteLine($"16進数: 0x{number:X}");
}
else
{
Console.WriteLine("正しい16進数を入力してください。");
}

このコードでは、空文字、0x付き、変換失敗を考慮しています。実務でユーザー入力を扱う場合は、このように例外に頼らない実装にすると安定します。

7. 16進数と10進数変換で押さえておきたい注意点

7-1. 数値として扱う場合と文字列として扱う場合の違い

16進数と10進数の変換で混乱しやすいのは、「数値」と「表示形式」を分けて考えていないケースです。

C#
int number = 255;

このnumberは数値です。10進数として表示すれば255、16進数として表示すればFFになります。

C#
Console.WriteLine(number);             // 255
Console.WriteLine(number.ToString("X")); // FF

"FF"は文字列です。計算に使うには、数値に変換する必要があります。

C#
string hex = "FF";

int number = Convert.ToInt32(hex, 16);

int result = number + 1;

Console.WriteLine(result); // 256

画面表示やログ出力では文字列、計算や比較では数値として扱うのが基本です。

7-2. 負の値を16進数に変換するときの挙動

負の値をToString("X")で16進数に変換すると、2の補数表現に基づいた結果になります。

C#
int value = -1;

Console.WriteLine(value.ToString("X")); // FFFFFFFF

-1を16進数で表示すると、intではFFFFFFFFになります。これは、32ビットの各ビットがすべて1になっている状態です。

C#
int value = -255;

Console.WriteLine(value.ToString("X")); // FFFFFF01

負の値を16進数で表示する場合、期待している表記が「マイナス付きの文字列」なのか、「ビット表現」なのかを明確にしておきましょう。

7-3. 符号付き整数と符号なし整数の違い

C#には、符号付き整数と符号なし整数があります。

意味
int符号付き32ビット整数負の値も扱える
uint符号なし32ビット整数0以上の値のみ
long符号付き64ビット整数大きな負数・正数を扱える
ulong符号なし64ビット整数大きな0以上の値を扱える

たとえば、FFFFFFFFuintとして見ると4294967295ですが、intのビット表現として見ると-1になります。

C#
using System.Globalization;

string hex = "FFFFFFFF";

uint unsignedValue = uint.Parse(hex, NumberStyles.HexNumber);
int signedValue = unchecked((int)unsignedValue);

Console.WriteLine(unsignedValue); // 4294967295
Console.WriteLine(signedValue); // -1

ビット列、ハッシュ値、ID、通信データなどを扱う場合は、符号付きか符号なしかを必ず確認しましょう。

7-4. 変換前に入力値チェックを行う重要性

16進数文字列を変換する前には、入力値チェックを行うことが重要です。特に、ユーザー入力や外部ファイル、APIレスポンスを扱う場合は、想定外の値が入る可能性があります。

チェックすべきポイントは次のとおりです。

チェック項目
nullではないかinput == null
空文字ではないかinput == ""
余計な空白がないかinput.Trim()
0x#を許可するかStartsWith()で判定
16進数として有効な文字だけかTryParseで判定
型の範囲に収まるかintlonguintを選ぶ

正規表現で事前チェックすることもできます。

C#
using System.Text.RegularExpressions;

string input = "FF";

bool isHex = Regex.IsMatch(input, @"\A[0-9a-fA-F]+\z");

Console.WriteLine(isHex); // True

ただし、正規表現で文字の妥当性を確認しても、数値型の範囲を超える可能性は残ります。最終的にはTryParseで変換できるか確認するのが安全です。

7-5. 用途に応じてint・long・uintを選ぶ考え方

C#で16進数と10進数を変換するときは、用途に応じて型を選ぶことが大切です。

用途おすすめの型
小さな整数値int
大きめの整数値long
0以上の32ビット値uint
0以上の64ビット値ulong
バイトデータbyte
非常に大きい値BigInteger

たとえば、カラーコード#FFFFFFは10進数で16777215なのでintで十分です。一方、FFFFFFFFを符号なしの値として扱いたい場合はuintを使うほうが自然です。

C#
using System.Globalization;

uint value = uint.Parse("FFFFFFFF", NumberStyles.HexNumber);

Console.WriteLine(value); // 4294967295

型選びを間違えると、オーバーフローや意図しない負の値につながることがあります。値の範囲と符号の有無を確認してから型を決めましょう。

8. C#の16進数・10進数変換に関するよくある質問

8-1. 16進数の「A〜F」は大文字と小文字どちらでもよいのか

どちらでも問題ありません。

C#
Console.WriteLine(Convert.ToInt32("FF", 16)); // 255
Console.WriteLine(Convert.ToInt32("ff", 16)); // 255
Console.WriteLine(Convert.ToInt32("Ff", 16)); // 255

16進数の入力では、A-Fa-fの両方が使えます。NumberStyles.AllowHexSpecifierでも、有効な16進数文字として0-9A-Fa-fが示されています。

出力時の大文字・小文字は、ToString("X")ToString("x")で切り替えます。

C#
int number = 255;

Console.WriteLine(number.ToString("X")); // FF
Console.WriteLine(number.ToString("x")); // ff

8-2. 「0x」が付いた文字列はそのまま変換できるのか

Convert.ToInt32(hex, 16)を使う場合は、0x付きの文字列も変換できます。

C#
int number = Convert.ToInt32("0xFF", 16);

Console.WriteLine(number); // 255

ただし、int.Parseint.TryParseNumberStyles.HexNumberを使う場合、0x付きの文字列はそのままでは変換できません。NumberStyles.AllowHexSpecifierでは、0x&hの接頭辞は使えないとされています。

C#
using System.Globalization;

string input = "0xFF";

input = input.Replace("0x", "", StringComparison.OrdinalIgnoreCase);

int number = int.Parse(input, NumberStyles.HexNumber);

Console.WriteLine(number); // 255

8-3. 10進数から2進数や8進数にも変換できるのか

できます。Convert.ToStringを使うと、2進数、8進数、10進数、16進数の文字列に変換できます。

C#
int number = 255;

Console.WriteLine(Convert.ToString(number, 2)); // 11111111
Console.WriteLine(Convert.ToString(number, 8)); // 377
Console.WriteLine(Convert.ToString(number, 10)); // 255
Console.WriteLine(Convert.ToString(number, 16)); // ff

Convert.ToString(number, 16)は小文字の16進数文字列を返します。大文字で表示したい場合は、ToUpper()を使うか、number.ToString("X")を使います。

C#
int number = 255;

Console.WriteLine(Convert.ToString(number, 16).ToUpper()); // FF
Console.WriteLine(number.ToString("X")); // FF

また、.NET 8以降では整数型に対して標準数値書式指定子"B"または"b"を使った2進数表示もサポートされています。

8-4. Convert.ToStringで16進数に変換できるのか

はい、できます。

C#
int number = 255;

string hex = Convert.ToString(number, 16);

Console.WriteLine(hex); // ff

Convert.ToString(number, 16)は、数値を16進数の文字列に変換します。ただし、結果は小文字になります。

大文字で表示したい場合は、次のようにします。

C#
int number = 255;

string hex = Convert.ToString(number, 16).ToUpper();

Console.WriteLine(hex); // FF

または、最初からToString("X")を使うとシンプルです。

C#
int number = 255;

string hex = number.ToString("X");

Console.WriteLine(hex); // FF

桁数をそろえたい場合も、ToString("X4")のように書けるため、表示目的ではToString("X")のほうが便利です。

8-5. 変換後の値を再計算に使うにはどうすればよいのか

16進数文字列を計算に使いたい場合は、まず数値型に変換します。

C#
string hex = "FF";

int number = Convert.ToInt32(hex, 16);

int result = number + 1;

Console.WriteLine(result); // 256

numberint型なので、通常の数値と同じように計算できます。

計算結果を再び16進数で表示したい場合は、ToString("X")を使います。

C#
string hex = "FF";

int number = Convert.ToInt32(hex, 16);
int result = number + 1;

Console.WriteLine(result); // 256
Console.WriteLine(result.ToString("X")); // 100

このように、計算するときは数値型、表示するときは文字列として扱うのが基本です。

まとめ

C#で16進数と10進数を相互変換する基本は、Convert.ToInt32ToString("X")です。

16進数の文字列を10進数の数値に変換する場合は、次のように書きます。

C#
int number = Convert.ToInt32("FF", 16);
Console.WriteLine(number); // 255

10進数の数値を16進数の文字列に変換する場合は、次のように書きます。

C#
int number = 255;
string hex = number.ToString("X");

Console.WriteLine(hex); // FF

小文字で表示したい場合はToString("x")、桁数をそろえたい場合はToString("X2")ToString("X4")を使います。

C#
int number = 255;

Console.WriteLine(number.ToString("x")); // ff
Console.WriteLine(number.ToString("X4")); // 00FF

また、入力値が正しいとは限らない場合は、int.TryParseNumberStyles.HexNumberを使って安全に変換するのがおすすめです。

C#
using System.Globalization;

string input = "FF";

if (int.TryParse(input, NumberStyles.HexNumber, null, out int number))
{
Console.WriteLine(number);
}
else
{
Console.WriteLine("変換できませんでした。");
}

C#で16進数と10進数を扱うときは、数値として扱うのか、文字列として表示するのかを分けて考えることが重要です。固定値や簡単な変換ではConvert.ToInt32ToString("X")を使い、ユーザー入力や外部データではTryParseを使うことで、安全で読みやすいコードになります。