C#のbyte型とは?範囲・使い方・変換・配列操作まで初心者向けに徹底解説

はじめに

C#でファイル操作、画像処理、通信処理、暗号化、バイナリデータの解析などを行うときによく登場するのがbyte型です。

byteは、0から255までの整数を扱うためのデータ型で、C#では非常に基本的な型のひとつです。ただし、普段の数値計算でよく使うintとは性質が少し異なり、範囲外の値を代入できなかったり、計算結果がint型になったりするため、初心者がつまずきやすいポイントもあります。

この記事では、C#のbyte型について、基本的な意味、範囲、宣言方法、型変換、byte[]配列の使い方、文字列やファイルとの変換、よくあるエラーまで初心者向けにわかりやすく解説します。

1. C#のbyte型とは?初心者向けに基本を解説

1-1. byte型は0〜255の整数を扱う値型

C#のbyte型は、0から255までの整数を扱うデータ型です。

C#
byte number = 100;

このように、byte型の変数には0以上255以下の整数を代入できます。

byteは「符号なし整数型」です。符号なしとは、マイナスの値を持たないという意味です。そのため、byte型では-1-100のような負の値は扱えません。

C#
byte value = 255; // OK
// byte error = -1; // エラー

C#では、byteは値型に分類されます。値型とは、変数そのものに値を保持する型のことです。intdoubleboolなども値型です。

1-2. byte型が使われる主な場面

byte型は、一般的な計算よりも、データを小さな単位で扱う場面でよく使われます。

代表的な使用場面は次のようなものです。

ファイルの読み書きでは、ファイルの中身をbyte[]として扱うことがあります。画像、PDF、音声、動画などのファイルも、内部的にはバイトの並びとして保存されています。

通信処理でも、ネットワークを通じて送受信されるデータはbyte[]として扱われることが多いです。

また、暗号化やハッシュ計算でもbyte配列がよく使われます。たとえば、パスワードのハッシュ値や暗号化されたデータは、人間が読む文字列ではなく、バイト列として扱われます。

C#
byte[] data = { 72, 101, 108, 108, 111 };

このように、byte型は「数値」というよりも「バイナリデータの1単位」として使われることが多い型です。

1-3. int型・sbyte型・char型との違い

byte型を理解するには、似た型との違いを知っておくことが大切です。

int型は、通常の整数計算でよく使われる型です。扱える範囲が非常に広く、一般的な数値処理ではintを使うことが多いです。

C#
int number = 1000;

一方、byte型は0から255までしか扱えません。その代わり、サイズが小さく、バイナリデータを扱うのに適しています。

sbyte型は、byteと同じく1バイトの整数型ですが、符号付きです。つまり、マイナスの値を扱えます。

C#
sbyte value = -100;

sbyteの範囲は-128から127です。byteは0から255なので、同じ1バイトでも扱える範囲が異なります。

char型は文字を扱う型です。byteと同じように数値的な側面もありますが、用途は文字を表すことです。

C#
char c = 'A';

byteはバイナリデータ、intは一般的な整数、sbyteは符号付きの1バイト整数、charは文字を扱う型と考えるとわかりやすいです。

1-4. byte型を理解するうえで重要な「8ビット」とは

byte型は1バイトのデータ型です。そして、1バイトは8ビットです。

ビットとは、コンピューターが扱う最小単位で、0または1のどちらかを表します。8ビットあると、次のように256通りの値を表現できます。

00000000
00000001
00000010
...
11111111

8ビットで表せる組み合わせは、2の8乗で256通りです。そのため、byte型は0から255までの256個の値を表現できます。

最小値: 0
最大値: 255

この「1バイト = 8ビット = 0〜255」という考え方は、C#のbyte型を理解するうえで非常に重要です。

2. C#のbyte型の範囲・サイズ・初期値

2-1. byte型の範囲は0〜255

C#のbyte型が扱える範囲は、0から255までです。

C#
byte min = 0;
byte max = 255;

0未満の値や256以上の値は代入できません。

C#
// byte a = -1;  // エラー
// byte b = 256; // エラー

この範囲を超える値を扱いたい場合は、intshortなど、より広い範囲を扱える型を使う必要があります。

2-2. byte型のサイズは1バイト

byte型のサイズは1バイトです。

C#
Console.WriteLine(sizeof(byte)); // 1

1バイトは8ビットなので、非常に小さなデータ単位です。

たとえば、1000個のbyteを配列で持つ場合、単純計算ではデータ部分は約1000バイトになります。大量のバイナリデータを扱う場面では、byte型の小ささが役立ちます。

2-3. byte型の既定値は0

C#のbyte型の既定値は0です。

フィールドや配列の要素として宣言した場合、明示的に値を設定しなければ0で初期化されます。

C#
byte[] values = new byte[3];

Console.WriteLine(values[0]); // 0
Console.WriteLine(values[1]); // 0
Console.WriteLine(values[2]); // 0

ただし、メソッド内のローカル変数は、使用する前に値を代入する必要があります。

C#
byte value;
// Console.WriteLine(value); // エラー

2-4. byte.MinValueとbyte.MaxValueの使い方

byte型の最小値と最大値は、byte.MinValuebyte.MaxValueで取得できます。

C#
Console.WriteLine(byte.MinValue); // 0
Console.WriteLine(byte.MaxValue); // 255

範囲チェックを行うときに便利です。

C#
int input = 200;

if (input >= byte.MinValue && input <= byte.MaxValue)
{
byte value = (byte)input;
Console.WriteLine(value);
}
else
{
Console.WriteLine("byte型の範囲外です");
}

数値をbyteに変換する前には、このように範囲を確認すると安全です。

2-5. 範囲外の値を代入するとどうなるか

byte型に範囲外の値を直接代入しようとすると、コンパイルエラーになります。

C#
// byte value = 300; // コンパイルエラー

また、実行時に変換する場合は、変換方法によって動作が異なります。

C#
int number = 300;

// byte value = (byte)number;

キャストを使うと、状況によっては値が切り詰められたような結果になることがあります。安全に変換したい場合は、checkedConvert.ToByte、範囲チェックを使うことが大切です。

C#
int number = 300;

try
{
byte value = Convert.ToByte(number);
}
catch (OverflowException)
{
Console.WriteLine("byte型の範囲外です");
}

3. C#のbyte型の宣言・代入・基本的な使い方

3-1. byte変数を宣言する基本構文

byte型の変数は、次のように宣言します。

C#
byte value;

宣言と同時に値を代入することもできます。

C#
byte value = 10;

変数名は任意ですが、何を表す値なのかわかりやすい名前にするのが基本です。

C#
byte age = 25;
byte red = 255;
byte level = 3;

3-2. byte型に数値を代入する方法

byte型には、0から255までの整数リテラルを代入できます。

C#
byte a = 0;
byte b = 100;
byte c = 255;

ただし、範囲外の数値は代入できません。

C#
// byte d = 256; // エラー

また、int型の変数をbyte型に代入する場合は、明示的な変換が必要です。

C#
int number = 100;
byte value = (byte)number;

C#では、たとえnumberの中身が100でbyteの範囲内であっても、intからbyteへの暗黙的な変換は行われません。

3-3. varでbyte型を扱うときの注意点

C#では、varを使うと型推論によって変数の型が決まります。

C#
var value = 10;

この場合、valuebyteではなくint型になります。整数リテラルは通常intとして扱われるためです。

byte型として扱いたい場合は、明示的に型を書くのがわかりやすいです。

C#
byte value = 10;

またはキャストを使うこともできます。

C#
var value = (byte)10;

ただし、初心者のうちはbyteを使いたい場面ではvarよりもbyteと明示したほうが安全です。

3-4. byte型を使った計算の基本

byte型の値は数値なので、加算や減算などの計算に使えます。

C#
byte a = 10;
byte b = 20;

int result = a + b;

Console.WriteLine(result); // 30

ここで注意したいのは、a + bの結果がbyteではなくintになることです。

そのため、次のコードはエラーになります。

C#
byte a = 10;
byte b = 20;

// byte result = a + b; // エラー

計算結果をbyteにしたい場合は、明示的なキャストが必要です。

C#
byte result = (byte)(a + b);

ただし、計算結果が255を超える可能性がある場合は、範囲外にならないよう注意が必要です。

3-5. byte型の加算・減算で起きやすいエラー

byte型の計算でよくあるエラーが、計算結果をそのままbyteに代入しようとするケースです。

C#
byte value = 10;

// value = value + 1; // エラー

value + 1の結果はint型になるため、byte型の変数にそのまま代入できません。

次のようにキャストすれば代入できます。

C#
value = (byte)(value + 1);

また、インクリメント演算子は使えます。

C#
byte value = 10;
value++;

Console.WriteLine(value); // 11

ただし、byteの最大値は255なので、255を超える可能性がある処理では注意が必要です。

C#
byte value = 255;

// value++; // オーバーフローに注意

通常の数値計算では、無理にbyteを使わずintを使うほうが安全でわかりやすいです。

4. C#のbyte型と型変換

4-1. intからbyteへ変換する方法

int型からbyte型へ変換するには、明示的な変換が必要です。

C#
int number = 100;
byte value = (byte)number;

ただし、intの値がbyteの範囲である0から255に収まっている必要があります。

安全に変換するなら、事前に範囲チェックを行います。

C#
int number = 100;

if (number >= byte.MinValue && number <= byte.MaxValue)
{
byte value = (byte)number;
Console.WriteLine(value);
}
else
{
Console.WriteLine("byteに変換できません");
}

4-2. byteからintへ変換する方法

byteからintへの変換は、暗黙的に行えます。

C#
byte value = 100;
int number = value;

intbyteよりも広い範囲を扱えるため、情報が失われる心配がありません。そのため、キャストを書く必要はありません。

C#
byte b = 200;
int i = b;

Console.WriteLine(i); // 200

4-3. キャストによる変換

キャストを使うと、明示的に型を変換できます。

C#
int number = 123;
byte value = (byte)number;

しかし、範囲外の値をキャストすると、意図しない値になる可能性があります。

C#
int number = 300;
byte value = (byte)number;

Console.WriteLine(value);

このようなコードは、初心者にとってわかりにくい結果になることがあります。値が範囲外になる可能性がある場合は、キャストだけに頼らず、範囲チェックやcheckedを使いましょう。

4-4. Convert.ToByteを使った変換

Convert.ToByteを使うと、さまざまな型からbyteへ変換できます。

C#
int number = 100;
byte value = Convert.ToByte(number);

Console.WriteLine(value); // 100

文字列から変換することもできます。

C#
string text = "123";
byte value = Convert.ToByte(text);

Console.WriteLine(value); // 123

ただし、範囲外の値を変換しようとするとOverflowExceptionが発生します。

C#
try
{
byte value = Convert.ToByte(300);
}
catch (OverflowException)
{
Console.WriteLine("byte型の範囲外です");
}

数値として解釈できない文字列の場合は、FormatExceptionが発生します。

C#
try
{
byte value = Convert.ToByte("abc");
}
catch (FormatException)
{
Console.WriteLine("数値に変換できません");
}

4-5. byte.Parseとbyte.TryParseの使い方

文字列をbyte型に変換するには、byte.Parseを使えます。

C#
string text = "200";
byte value = byte.Parse(text);

Console.WriteLine(value); // 200

ただし、変換できない文字列や範囲外の値を指定すると例外が発生します。

C#
// byte value = byte.Parse("300"); // OverflowException
// byte value = byte.Parse("abc"); // FormatException

例外を避けたい場合は、byte.TryParseを使うのがおすすめです。

C#
string text = "200";

if (byte.TryParse(text, out byte value))
{
Console.WriteLine($"変換成功: {value}");
}
else
{
Console.WriteLine("変換できませんでした");
}

TryParseは、変換に成功した場合はtrue、失敗した場合はfalseを返します。ユーザー入力を扱う場合は、ParseよりもTryParseのほうが安全です。

4-6. 文字列をbyte型に変換する方法

文字列を単一のbyte値に変換する場合、文字列が0から255までの数値を表している必要があります。

C#
string text = "50";
byte value = byte.Parse(text);

安全に処理するなら、次のように書きます。

C#
string text = "50";

if (byte.TryParse(text, out byte value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("byteに変換できない文字列です");
}

一方で、文字列そのものをバイト列に変換したい場合は、byte.ParseではなくEncodingを使います。

C#
using System.Text;

string text = "Hello";
byte[] bytes = Encoding.UTF8.GetBytes(text);

「文字列の数値をbyteにする」のか、「文字列データをbyte[]にする」のかを区別することが重要です。

4-7. 変換時のOverflowExceptionに注意する

byte型の範囲は0から255なので、それを超える値を変換しようとするとOverflowExceptionが発生することがあります。

C#
try
{
string text = "999";
byte value = byte.Parse(text);
}
catch (OverflowException)
{
Console.WriteLine("値がbyte型の範囲を超えています");
}

ユーザー入力や外部データを扱う場合は、想定外の値が入る可能性があります。そのため、TryParseや範囲チェックを使って、例外に頼らない処理を書くことが大切です。

C#
string text = "999";

if (byte.TryParse(text, out byte value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("0〜255の数値を入力してください");
}

4-8. checkedとuncheckedによるオーバーフロー制御

C#では、整数演算のオーバーフローをcheckeduncheckedで制御できます。

checkedを使うと、オーバーフローが発生したときに例外を発生させます。

C#
try
{
int number = 300;

checked
{
byte value = (byte)number;
Console.WriteLine(value);
}
}
catch (OverflowException)
{
Console.WriteLine("オーバーフローが発生しました");
}

一方、uncheckedを使うと、オーバーフローを検出せずに変換します。

C#
int number = 300;

unchecked
{
byte value = (byte)number;
Console.WriteLine(value);
}

安全性を重視する場合は、checkedや明示的な範囲チェックを使うとよいでしょう。

5. C#のbyte配列とは?byte[]の基本

5-1. byte配列が必要になる理由

byte型が1つのバイトを表すのに対して、byte[]は複数のバイトをまとめて扱う配列です。

C#
byte[] data = { 1, 2, 3, 4, 5 };

ファイル、画像、音声、通信データ、暗号化データなどは、1つのbyteではなく、多数のバイトの集まりとして扱われます。そのため、実際の開発ではbyte単体よりもbyte[]を使う場面が多くあります。

たとえば、テキストをUTF-8のバイト列に変換すると、byte[]として取得できます。

C#
using System.Text;

byte[] bytes = Encoding.UTF8.GetBytes("Hello");

5-2. byte[]を宣言・初期化する方法

byte[]は次のように宣言します。

C#
byte[] bytes;

サイズを指定して初期化する場合は、次のように書きます。

C#
byte[] bytes = new byte[5];

この場合、要素数5のbyte配列が作成され、各要素は0で初期化されます。

C#
Console.WriteLine(bytes[0]); // 0

初期値を指定して作成することもできます。

C#
byte[] bytes = new byte[] { 10, 20, 30 };

C#では、次のように省略して書くこともできます。

C#
byte[] bytes = { 10, 20, 30 };

5-3. byte配列の要素にアクセスする方法

byte配列の要素には、インデックスを使ってアクセスします。

C#
byte[] bytes = { 10, 20, 30 };

Console.WriteLine(bytes[0]); // 10
Console.WriteLine(bytes[1]); // 20
Console.WriteLine(bytes[2]); // 30

配列のインデックスは0から始まります。最初の要素はbytes[0]、2番目の要素はbytes[1]です。

値を変更することもできます。

C#
bytes[1] = 99;

Console.WriteLine(bytes[1]); // 99

ただし、存在しないインデックスにアクセスするとエラーになります。

C#
// Console.WriteLine(bytes[3]); // IndexOutOfRangeException

5-4. byte配列をループで処理する方法

byte配列の中身を順番に処理するには、for文やforeach文を使います。

C#
byte[] bytes = { 10, 20, 30 };

for (int i = 0; i < bytes.Length; i++)
{
Console.WriteLine(bytes[i]);
}

要素を読み取るだけなら、foreach文が簡潔です。

C#
foreach (byte b in bytes)
{
Console.WriteLine(b);
}

インデックス番号が必要な場合はfor文、要素を順番に取り出すだけならforeach文を使うとよいでしょう。

5-5. byte配列の長さを取得する方法

byte配列の長さは、Lengthプロパティで取得できます。

C#
byte[] bytes = { 10, 20, 30 };

Console.WriteLine(bytes.Length); // 3

配列をループ処理するときは、固定の数値ではなくLengthを使うのが基本です。

C#
for (int i = 0; i < bytes.Length; i++)
{
Console.WriteLine(bytes[i]);
}

これにより、配列の長さが変わっても安全に処理できます。

5-6. byte配列をコピーする方法

byte配列をコピーする方法はいくつかあります。

もっともわかりやすいのは、Array.Copyを使う方法です。

C#
byte[] source = { 1, 2, 3, 4, 5 };
byte[] destination = new byte[5];

Array.Copy(source, destination, source.Length);

一部だけコピーすることもできます。

C#
byte[] source = { 1, 2, 3, 4, 5 };
byte[] destination = new byte[3];

Array.Copy(source, 1, destination, 0, 3);

foreach (byte b in destination)
{
Console.WriteLine(b);
}

この例では、sourceのインデックス1から3個分をdestinationにコピーしています。

6. byte配列の変換・操作方法

6-1. byte配列と文字列を相互変換する方法

C#で文字列とbyte[]を変換するには、System.Text.Encodingを使います。

文字列からbyte[]に変換する例です。

C#
using System.Text;

string text = "こんにちは";
byte[] bytes = Encoding.UTF8.GetBytes(text);

byte[]から文字列に戻すには、GetStringを使います。

C#
string result = Encoding.UTF8.GetString(bytes);

Console.WriteLine(result); // こんにちは

重要なのは、変換時に同じ文字コードを使うことです。UTF-8でバイト列にしたものは、UTF-8で文字列に戻す必要があります。

6-2. Encoding.UTF8.GetBytesの使い方

Encoding.UTF8.GetBytesは、文字列をUTF-8形式のbyte[]に変換するメソッドです。

C#
using System.Text;

string text = "Hello";
byte[] bytes = Encoding.UTF8.GetBytes(text);

foreach (byte b in bytes)
{
Console.WriteLine(b);
}

英字だけでなく、日本語も変換できます。

C#
string text = "あ";
byte[] bytes = Encoding.UTF8.GetBytes(text);

Console.WriteLine(bytes.Length);

日本語の文字は、UTF-8では複数バイトで表現されることがあります。そのため、文字数とバイト数は必ずしも一致しません。

C#
string text = "abc";
Console.WriteLine(text.Length); // 3

byte[] bytes = Encoding.UTF8.GetBytes(text);
Console.WriteLine(bytes.Length); // 3

一方、日本語では次のようにバイト数が文字数より多くなることがあります。

C#
string text = "あいう";
byte[] bytes = Encoding.UTF8.GetBytes(text);

Console.WriteLine(text.Length);
Console.WriteLine(bytes.Length);

6-3. Encoding.UTF8.GetStringの使い方

Encoding.UTF8.GetStringは、UTF-8のbyte[]を文字列に変換するメソッドです。

C#
using System.Text;

byte[] bytes = { 72, 101, 108, 108, 111 };
string text = Encoding.UTF8.GetString(bytes);

Console.WriteLine(text); // Hello

一部の範囲だけを文字列に変換することもできます。

C#
byte[] bytes = Encoding.UTF8.GetBytes("Hello World");

string text = Encoding.UTF8.GetString(bytes, 0, 5);

Console.WriteLine(text); // Hello

文字コードが一致していないと、文字化けの原因になります。たとえば、Shift_JISで作られたバイト列をUTF-8として読み込むと、正しく表示されないことがあります。

6-4. byte配列と16進数文字列を変換する方法

バイナリデータは、16進数文字列として表示すると確認しやすくなります。

たとえば、byteの値255は16進数ではFFです。

C#
byte value = 255;
Console.WriteLine(value.ToString("X2")); // FF

byte[]を16進数文字列に変換するには、次のようにできます。

C#
byte[] bytes = { 0, 15, 16, 255 };

string hex = BitConverter.ToString(bytes).Replace("-", "");

Console.WriteLine(hex); // 000F10FF

新しい.NET環境では、Convert.ToHexStringも便利です。

C#
byte[] bytes = { 0, 15, 16, 255 };

string hex = Convert.ToHexString(bytes);

Console.WriteLine(hex); // 000F10FF

16進数文字列をbyte[]に戻す場合は、2文字ずつ変換します。

C#
string hex = "000F10FF";
byte[] bytes = new byte[hex.Length / 2];

for (int i = 0; i < bytes.Length; i++)
{
bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}

16進数は、ハッシュ値、暗号化データ、バイナリ解析などでよく使われます。

6-5. BitConverterで数値とbyte配列を変換する方法

BitConverterを使うと、数値型とbyte[]を相互に変換できます。

C#
int number = 123456;
byte[] bytes = BitConverter.GetBytes(number);

byte[]からintに戻すには、BitConverter.ToInt32を使います。

C#
int result = BitConverter.ToInt32(bytes, 0);

Console.WriteLine(result); // 123456

doubleshortなど、他の数値型にも対応しています。

C#
double value = 3.14;
byte[] bytes = BitConverter.GetBytes(value);

double result = BitConverter.ToDouble(bytes, 0);

ただし、BitConverterを使うときはエンディアンに注意が必要です。エンディアンとは、複数バイトの数値をどの順番で並べるかというルールです。

環境によってバイト順が問題になる場合は、BitConverter.IsLittleEndianを確認し、必要に応じて配列を反転します。

C#
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}

6-6. Array.CopyやBuffer.BlockCopyを使った配列操作

byte[]をコピーするには、Array.Copyが使えます。

C#
byte[] source = { 1, 2, 3, 4, 5 };
byte[] destination = new byte[5];

Array.Copy(source, destination, source.Length);

バイト単位で高速にコピーしたい場合は、Buffer.BlockCopyを使うこともあります。

C#
byte[] source = { 1, 2, 3, 4, 5 };
byte[] destination = new byte[5];

Buffer.BlockCopy(source, 0, destination, 0, source.Length);

Buffer.BlockCopyは、配列内のデータをバイト単位でコピーするため、バイナリデータの処理で使われることがあります。

一部だけコピーする例です。

C#
byte[] source = { 10, 20, 30, 40, 50 };
byte[] destination = new byte[3];

Buffer.BlockCopy(source, 1, destination, 0, 3);

どちらを使うべきか迷った場合、通常は読みやすいArray.Copyで十分です。性能が重要な場面ではBuffer.BlockCopySpan<byte>を検討します。

6-7. Span<byte>・Memory<byte>を使う場面

Span<byte>Memory<byte>は、配列の一部を効率よく扱うための型です。

たとえば、byte[]の一部だけを処理したい場合、従来は新しい配列を作ってコピーすることがありました。しかし、コピーが増えるとメモリ使用量や処理時間が増えてしまいます。

Span<byte>を使うと、元の配列をコピーせずに一部分だけを参照できます。

C#
byte[] data = { 1, 2, 3, 4, 5 };

Span<byte> span = data.AsSpan(1, 3);

foreach (byte b in span)
{
Console.WriteLine(b);
}

この例では、dataのインデックス1から3個分をSpan<byte>として扱っています。

Memory<byte>は、非同期処理や長期間保持するデータに向いています。初心者のうちは、まずbyte[]の基本を理解し、性能やメモリ効率が必要になったときにSpan<byte>Memory<byte>を学ぶとよいでしょう。

7. byte型・byte配列の実践的な使用例

7-1. ファイルをbyte配列として読み込む

ファイルの内容をすべてbyte[]として読み込むには、File.ReadAllBytesを使います。

C#
byte[] data = File.ReadAllBytes("sample.bin");

Console.WriteLine(data.Length);

画像ファイルやPDFファイルも、同じようにbyte[]として読み込めます。

C#
byte[] imageBytes = File.ReadAllBytes("image.png");

ファイルサイズが大きい場合は、すべてを一度にメモリへ読み込むと負荷が高くなることがあります。その場合は、ストリームを使って少しずつ読み込む方法を検討します。

7-2. byte配列をファイルに書き込む

byte[]をファイルに書き込むには、File.WriteAllBytesを使います。

C#
byte[] data = { 72, 101, 108, 108, 111 };

File.WriteAllBytes("output.bin", data);

文字列をバイト配列に変換してからファイルに書き込むこともできます。

C#
using System.Text;

string text = "Hello";
byte[] bytes = Encoding.UTF8.GetBytes(text);

File.WriteAllBytes("hello.txt", bytes);

このように、ファイル操作ではbyte[]がよく使われます。

7-3. 画像データをbyte配列で扱う

画像ファイルも内部的にはバイトの集まりです。そのため、画像をデータベースに保存したり、Web APIで送受信したりする場合にbyte[]を使うことがあります。

C#
byte[] imageBytes = File.ReadAllBytes("photo.jpg");

読み込んだ画像データを別のファイルとして保存することもできます。

C#
File.WriteAllBytes("copy.jpg", imageBytes);

画像処理ライブラリを使う場合でも、入力や出力としてbyte[]を扱う場面があります。

7-4. 通信データをbyte配列で扱う

ネットワーク通信では、送受信するデータをbyte[]として扱うことが多いです。

たとえば、文字列を送信する場合でも、実際には文字列をバイト列に変換して送ります。

C#
using System.Text;

string message = "Hello";
byte[] data = Encoding.UTF8.GetBytes(message);

受信したbyte[]を文字列に戻す場合は、同じ文字コードを使います。

C#
string received = Encoding.UTF8.GetString(data);

通信処理では、データの先頭数バイトにヘッダー情報が入っていたり、特定の位置に長さや種類を表す値が入っていたりすることがあります。そのような場合、byte[]のインデックスを使ってデータを解析します。

7-5. バイナリデータを解析する

バイナリファイルや通信パケットを解析するとき、byte[]の中身を順番に読み取ることがあります。

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

foreach (byte b in data)
{
Console.WriteLine(b.ToString("X2"));
}

16進数で表示すると、バイナリデータの確認がしやすくなります。

C#
Console.WriteLine(BitConverter.ToString(data));

特定の位置にある値を読み取る例です。

C#
byte type = data[0];
byte code = data[1];
byte flag = data[2];

Console.WriteLine(type);
Console.WriteLine(code);
Console.WriteLine(flag);

バイナリデータの解析では、仕様書に従って「何バイト目に何の情報があるか」を正しく読み取ることが重要です。

7-6. ハッシュ値や暗号化処理でbyte配列を使う

ハッシュ計算や暗号化処理でも、byte[]はよく使われます。

たとえば、文字列のハッシュ値を計算する場合、まず文字列をbyte[]に変換します。

C#
using System.Security.Cryptography;
using System.Text;

string text = "password";
byte[] input = Encoding.UTF8.GetBytes(text);

byte[] hash = SHA256.HashData(input);

string hex = Convert.ToHexString(hash);

Console.WriteLine(hex);

ハッシュ値は、元の文字列ではなくバイト列として計算されます。その結果もbyte[]として得られるため、表示したい場合は16進数文字列などに変換します。

暗号化処理でも、平文、鍵、初期化ベクトル、暗号文などをbyte[]として扱うことが一般的です。

8. C#のbyte型でよくあるエラーと対処法

8-1. 「Cannot implicitly convert type 'int' to 'byte'」の原因

C#でbyteを使っていると、次のようなエラーに出会うことがあります。

Cannot implicitly convert type 'int' to 'byte'

これは、int型の値をbyte型に暗黙的に変換できないという意味です。

たとえば、次のコードはエラーになります。

C#
int number = 100;
// byte value = number; // エラー

intbyteよりも広い範囲を扱えるため、値によってはbyteに収まりません。そのため、C#は自動変換を許可しません。

対処するには、明示的なキャストを使います。

C#
byte value = (byte)number;

ただし、範囲外の可能性がある場合は、事前にチェックしましょう。

C#
if (number >= byte.MinValue && number <= byte.MaxValue)
{
byte value = (byte)number;
}

8-2. byte同士の計算結果がintになる理由

byte同士を計算すると、結果はintになります。

C#
byte a = 10;
byte b = 20;

// byte result = a + b; // エラー
int result = a + b;

これは、C#の整数演算では、byteshortなどの小さな整数型が計算時にintへ昇格されるためです。

byteに戻したい場合は、明示的にキャストします。

C#
byte result = (byte)(a + b);

ただし、合計が255を超えると正しく扱えない可能性があります。

C#
byte a = 200;
byte b = 100;

int sum = a + b; // 300

この場合、byteには300を格納できないため、intのまま扱うほうが安全です。

8-3. byte型の範囲外で発生するエラー

byte型は0から255までしか扱えないため、範囲外の値に注意が必要です。

C#
// byte value = 300; // コンパイルエラー

文字列から変換する場合も、範囲外なら失敗します。

C#
try
{
byte value = byte.Parse("300");
}
catch (OverflowException)
{
Console.WriteLine("byte型の範囲外です");
}

ユーザー入力を扱う場合は、byte.TryParseを使うと安全です。

C#
string input = "300";

if (byte.TryParse(input, out byte value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("0〜255の数値を入力してください");
}

8-4. Parse失敗時のエラーを防ぐ方法

byte.Parseは、変換に失敗すると例外を発生させます。

C#
// byte value = byte.Parse("abc"); // FormatException

ユーザー入力や外部ファイルの値を変換する場合、常に正しい数値が入っているとは限りません。そのため、基本的にはTryParseを使うのがおすすめです。

C#
string input = "abc";

if (byte.TryParse(input, out byte value))
{
Console.WriteLine($"値: {value}");
}
else
{
Console.WriteLine("byte型に変換できません");
}

TryParseを使えば、例外処理を書かなくても変換の成功・失敗を判定できます。

8-5. 文字コードの違いによる文字化け

byte[]と文字列を変換するときに、文字コードが一致していないと文字化けが発生します。

C#
byte[] bytes = Encoding.UTF8.GetBytes("こんにちは");
string text = Encoding.UTF8.GetString(bytes);

このように、UTF-8でエンコードしたデータはUTF-8でデコードする必要があります。

もし別の文字コードで作られたデータをUTF-8として読み込むと、正しく表示されない場合があります。

文字列とbyte[]を変換するときは、必ず文字コードを明示しましょう。

C#
using System.Text;

Encoding encoding = Encoding.UTF8;

byte[] bytes = encoding.GetBytes("テスト");
string text = encoding.GetString(bytes);

特に、日本語を扱う場合は文字コードの違いが問題になりやすいため注意が必要です。

8-6. byte配列のインデックス範囲外エラー

byte[]の存在しない位置にアクセスすると、IndexOutOfRangeExceptionが発生します。

C#
byte[] bytes = { 10, 20, 30 };

// Console.WriteLine(bytes[3]); // エラー

配列のインデックスは0から始まるため、要素数が3の場合、使えるインデックスは0、1、2です。

安全にアクセスするには、Lengthを使って範囲を確認します。

C#
int index = 2;

if (index >= 0 && index < bytes.Length)
{
Console.WriteLine(bytes[index]);
}
else
{
Console.WriteLine("インデックスが範囲外です");
}

ループ処理でも、i <= bytes.Lengthではなくi < bytes.Lengthと書く必要があります。

C#
for (int i = 0; i < bytes.Length; i++)
{
Console.WriteLine(bytes[i]);
}

9. byte型を使うときの注意点とベストプラクティス

9-1. 通常の数値計算ではintを使うべき理由

byte型はメモリ使用量が少ないため、すべての小さな数値に使いたくなるかもしれません。しかし、通常の数値計算ではintを使うのが一般的です。

理由は、byte同士の計算結果がintになるため、毎回キャストが必要になりやすいからです。

C#
byte a = 10;
byte b = 20;
byte result = (byte)(a + b);

このようなコードは、intを使えばもっと自然に書けます。

C#
int a = 10;
int b = 20;
int result = a + b;

年齢、個数、回数、スコアなど、通常の数値を扱う場合は、基本的にintを使うとよいでしょう。

9-2. byte型はメモリ節約やバイナリ処理で活用する

byte型が特に役立つのは、バイナリデータを扱う場面です。

ファイルの内容、画像データ、通信データ、暗号化データ、ハッシュ値などは、byte[]として扱うことが多くあります。

C#
byte[] fileData = File.ReadAllBytes("sample.dat");

また、0から255までの値を大量に保存する必要がある場合にも、byte型はメモリ節約に役立ちます。

ただし、単に「小さい数値だから」という理由だけでbyteを使うと、計算時の型変換や範囲チェックが増えてコードが読みにくくなることがあります。

9-3. 範囲チェックを行ってから変換する

intや文字列からbyteに変換する場合は、範囲チェックを行うことが大切です。

C#
int number = 200;

if (number >= byte.MinValue && number <= byte.MaxValue)
{
byte value = (byte)number;
}
else
{
Console.WriteLine("byte型の範囲外です");
}

文字列の場合は、byte.TryParseを使うと簡潔です。

C#
string input = "200";

if (byte.TryParse(input, out byte value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("変換できません");
}

外部から受け取った値は、必ずしも期待通りとは限りません。安全なコードを書くためには、変換前のチェックを習慣にしましょう。

9-4. 文字列変換ではEncodingを明示する

文字列とbyte[]を変換するときは、Encodingを明示することが重要です。

C#
using System.Text;

byte[] bytes = Encoding.UTF8.GetBytes("こんにちは");
string text = Encoding.UTF8.GetString(bytes);

文字コードをあいまいにすると、環境やデータの形式によって文字化けが起こることがあります。

特に、Web APIやファイル入出力ではUTF-8が使われることが多いため、明示的にEncoding.UTF8を指定すると意図が伝わりやすくなります。

C#
Encoding encoding = Encoding.UTF8;

文字列をバイト列にする処理では、「どの文字コードで変換したのか」を常に意識しましょう。

9-5. 可読性を重視して適切な型を選ぶ

型を選ぶときは、メモリ効率だけでなく可読性も大切です。

たとえば、次のような場合はbyteが適しています。

C#
byte[] imageData;
byte[] hash;
byte colorValue;

一方、通常の計算やカウント処理ではintのほうが自然です。

C#
int count;
int total;
int score;

byte型は便利ですが、使いどころを間違えると、キャストや範囲チェックが増えてコードが複雑になります。

「この値は本当に0〜255の範囲に限定されるのか」「バイナリデータとして扱う必要があるのか」を考えて、適切な型を選びましょう。

10. C#のbyte型に関するよくある質問

10-1. C#のbyte型の最大値はいくつ?

C#のbyte型の最大値は255です。

C#
Console.WriteLine(byte.MaxValue); // 255

最小値は0です。

C#
Console.WriteLine(byte.MinValue); // 0

つまり、byte型で扱える範囲は0から255までです。

10-2. byteとsbyteの違いは?

byteは符号なしの1バイト整数型で、0から255までを扱います。

C#
byte value = 255;

sbyteは符号付きの1バイト整数型で、-128から127までを扱います。

C#
sbyte value = -100;

どちらもサイズは1バイトですが、マイナスを扱えるかどうかが違います。通常、バイナリデータを扱う場合はbyteを使うことが多いです。

10-3. byteとintはどちらを使うべき?

通常の数値計算ではintを使うのがおすすめです。

C#
int count = 100;

byteは、0から255までの値に限定したい場合や、ファイル・画像・通信データなどのバイナリデータを扱う場合に使います。

C#
byte[] data = File.ReadAllBytes("sample.bin");

小さな数値だからといって、必ずbyteを使う必要はありません。計算しやすさや可読性を考えると、一般的な整数にはintが向いています。

10-4. byte配列を文字列に変換するには?

byte[]を文字列に変換するには、Encoding.GetStringを使います。

C#
using System.Text;

byte[] bytes = Encoding.UTF8.GetBytes("Hello");
string text = Encoding.UTF8.GetString(bytes);

Console.WriteLine(text); // Hello

文字コードは、バイト配列を作成したときと同じものを指定する必要があります。

UTF-8で作ったbyte[]は、UTF-8で文字列に戻します。

10-5. byte型でマイナスの値は扱える?

byte型ではマイナスの値を扱えません。

C#
// byte value = -1; // エラー

byte型の範囲は0から255です。

マイナスの値を扱いたい場合は、sbyteshortintなどを使います。

C#
sbyte value = -1;
int number = -100;

ただし、sbyteは-128から127までしか扱えないため、通常の整数計算ではintを使うことが多いです。

10-6. byte配列はどんな場面で使う?

byte[]は、バイナリデータを扱う場面でよく使われます。

代表的な例は、ファイルの読み書き、画像データの処理、ネットワーク通信、暗号化、ハッシュ計算、バイナリファイルの解析などです。

C#
byte[] fileData = File.ReadAllBytes("sample.dat");

文字列も、通信や保存の際にはbyte[]に変換されることがあります。

C#
byte[] bytes = Encoding.UTF8.GetBytes("Hello");

byte[]は、C#で低レベルなデータ処理を行ううえで非常に重要な型です。

まとめ

C#のbyte型は、0から255までの整数を扱う1バイトの値型です。サイズが小さく、バイナリデータを扱う場面でよく使われます。

byte型の基本的な特徴は、範囲が0〜255、サイズが1バイト、既定値が0であることです。最大値と最小値は、byte.MaxValuebyte.MinValueで確認できます。

一方で、byte型は通常の数値計算にはあまり向いていません。byte同士を計算すると結果がintになるため、キャストが必要になることがあります。年齢、個数、合計値などの一般的な数値には、基本的にintを使うのがわかりやすいです。

byteが特に活躍するのは、byte[]として複数のバイトを扱う場面です。ファイル、画像、通信、暗号化、ハッシュ値、バイナリ解析などでは、byte[]が頻繁に使われます。

また、文字列とbyte[]を変換する際は、Encoding.UTF8.GetBytesEncoding.UTF8.GetStringを使い、文字コードを明示することが重要です。型変換では、範囲外の値によるOverflowExceptionや、変換失敗によるエラーを防ぐために、TryParseや範囲チェックを活用しましょう。

C#のbyte型を正しく理解すると、ファイル操作や通信処理、画像処理、暗号化処理など、より実践的なプログラムを書けるようになります。まずは、byteの範囲と使いどころを押さえ、必要に応じてbyte[]EncodingBitConverterなどの関連機能も使いこなしていきましょう。