Unity & C# 学習教材

プリミティブ型と型変換

C# には値の種類ごとに「型」が用意されています。どの型を選ぶかで、扱える値の範囲・精度・メモリの使用量が変わります。このページでは数値・文字・文字列の型を詳しく学び、型同士の変換と異なる型の演算のルールを理解します。

学習目標

前提知識


1. 整数型の種類と表現範囲

C# の整数型は「何ビットで値を記憶するか」と「負の数を扱うか(符号)」の組み合わせで決まります。

型名 ビット数 符号 最小値 最大値
byte 8 なし 0 255
sbyte 8 あり -128 127
short 16 あり -32,768 32,767
ushort 16 なし 0 65,535
int 32 あり -2,147,483,648 2,147,483,647
uint 32 なし 0 4,294,967,295
long 64 あり -9,223,372,036,854,775,808 9,223,372,036,854,775,807
ulong 64 なし 0 18,446,744,073,709,551,615

💡 型の選び方: 迷ったら int を使ってください。Unity でも int が最もよく使われる整数型です。longint の範囲を超える大きな数(累計スコアなど)、byte は色の成分(0〜255)や小さな数値に使います。

型の最大値・最小値はコードから確認できます。

int.MaxValueint 型が表現できる最大値の定数(2147483647)。byte.MaxValuelong.MaxValue など他の整数型でも同様に使える。

書式:int.MaxValue フィールド

1
public const int MaxValue = 2147483647;

int.MinValueint 型が表現できる最小値の定数(-2147483648)。

書式:int.MinValue フィールド

1
public const int MinValue = -2147483648;
1
2
3
Console.WriteLine(int.MaxValue);  // 2147483647
Console.WriteLine(int.MinValue);  // -2147483648
// 他の型も同様: byte.MaxValue → 255, long.MaxValue → 9223372036854775807

「符号あり」と「符号なし」

整数型には 符号あり(signed)符号なし(unsigned) の2種類があります。

8 ビットの例で比べると:

1
2
符号あり sbyte: -128 〜 127  (256通りを負・0・正に振り分ける)
符号なし byte:     0 〜 255  (256通りをすべて 0 以上に使う)

どちらも 2⁸ = 256 通りの値を表現しますが、範囲の割り当てが異なります。

オーバーフロー

変数に入れられる範囲を超えた計算をするとオーバーフローが発生します。C# のデフォルト動作では例外は発生せず、値が反対端から折り返します。

1
2
3
int maxInt = int.MaxValue;
Console.WriteLine(maxInt);      // 2147483647
Console.WriteLine(maxInt + 1);  // -2147483648 (最大値の次は最小値に折り返す)

⚠️ 注意: オーバーフローは実行時に無警告で起きます。意図しない計算結果にならないよう、値の範囲に合った型を選ぶことが大切です。

🔍 なぜ折り返すのか・もっと深く知りたい方へ: 2の補数による負数表現のしくみ、intSystem.Int32 の関係、16進数/2進数リテラルの書き方などは補足ページで解説しています → 数値リテラルと型エイリアス(補足)


2. 浮動小数点型の種類と精度

小数を扱う型は3種類あります。

型名 ビット数 有効桁数 主な用途
float 32 約7桁 Unity の座標・角度など(パフォーマンス優先)
double 64 約15〜17桁 一般的な小数計算(C# のデフォルト)
decimal 128 約28〜29桁 金融計算など(誤差を許容できない場合)

リテラルのサフィックス

小数リテラルは既定で double 型です。floatdecimal のリテラルを書くにはサフィックスを付けます。

書き方
3.14 double
3.14f float
3.14m decimal
1
2
3
double  d = 3.14;   // double リテラルをそのまま代入
float   f = 3.14f;  // f サフィックスで float リテラル
decimal m = 3.14m;  // m サフィックスで decimal リテラル
1
2
float f = 3.14;   // ❌ コンパイルエラー: double は float に暗黙的に変換できない
float f = 3.14f;  // ✅ OK

💡 Unity では float をよく使う: Unity の Vector3transform.position など、ほとんどの値が float 型です。Unity で小数を扱うときは 3.14f のように f を付ける習慣をつけましょう。

浮動小数点数の誤差

floatdouble は値を2進数で近似して記憶します。そのため、計算結果に小さな誤差が出ることがあります。

1
2
Console.WriteLine(0.1 + 0.2);         // 0.30000000000000004
Console.WriteLine(0.1 + 0.2 == 0.3);  // False

金融計算など誤差を許容できない場面では decimal を使ってください。


3. char — 1文字を扱う型

char1文字を表す型です。リテラルはシングルクォート(' で囲みます。

1
2
char c = 'A';
Console.WriteLine(c);  // A

char は内部的に Unicode のコードポイント(0〜65535 の整数)として記憶されています。そのため整数への変換や算術演算も行えます。

1
2
3
char c = 'A';
Console.WriteLine((int)c);          // 65  ('A' の Unicode コードポイント)
Console.WriteLine((char)('A' + 1)); // B   (コードポイント 66 → 'B')

エスケープシーケンス

特殊文字は \ を使ったエスケープシーケンスで表現します。

シーケンス 意味
'\n' 改行
'\t' タブ
'\\' バックスラッシュ自体
'\'' シングルクォート自体

4. string — 文字列を扱う型

string文字の並び(シーケンス) を表す型です。リテラルはダブルクォート(" で囲みます。

1
2
3
string name = "Alice";
Console.WriteLine(name);          // Alice
Console.WriteLine(name.Length);   // 5 (文字数)

charstring の違い

比較項目 char string
文字数 必ず1文字 0文字以上(何文字でも可)
リテラルの囲み ' シングルクォート " ダブルクォート
'A' "Alice"
1
2
3
char   c = 'A';      // ✅ char は1文字
string s = "A";      // ✅ string は1文字でもOK
char   c = "A";      // ❌ コンパイルエラー: string を char には代入できない

文字列の連結

+ 演算子で文字列を連結できます。

1
2
3
4
string firstName = "Alice";
string lastName  = "Smith";
string fullName  = firstName + " " + lastName;
Console.WriteLine(fullName);  // Alice Smith

string 内のエスケープシーケンス

char と同じエスケープシーケンスが string 内でも使えます。

シーケンス 意味
"\n" 改行
"\t" タブ
"\\" バックスラッシュ
"\"" ダブルクォート
1
2
3
Console.WriteLine("1行目\n2行目");  // 改行して2行に出力
Console.WriteLine("A\tB");          // タブで区切って出力
Console.WriteLine("\"Hello\"");     // "Hello"(ダブルクォートを含む文字列)

5. 型変換

異なる型の値を別の型に変換する操作を型変換と呼びます。

暗黙的型変換

情報が失われない(= より広い型への)変換は自動で行われます。これを暗黙的型変換(implicit conversion) と呼びます。

1
2
3
int    i = 42;
long   l = i;   // int → long へ暗黙的に変換
double d = i;   // int → double へ暗黙的に変換

暗黙的型変換が可能な主な方向(矢印の向きに自動変換される):

1
byte → short → int → long → float → double

明示的型変換(キャスト)

情報が失われる可能性のある変換は明示的に指定する必要があります。これをキャスト(cast) と呼びます。

書式:キャスト

1
(変換先の型)式
要素 説明
(変換先の型) 変換したい型名をカッコで囲む
変換する値
1
2
3
double d = 3.7;
int    i = (int)d;         // double → int にキャスト
Console.WriteLine(i);      // 3 (小数点以下は切り捨て)

⚠️ 注意: キャストによる小数→整数の変換は切り捨てです。四捨五入ではありません。3.9 をキャストしても 3 になります。

表現範囲を超えた値をキャストするとオーバーフローが起きます。

1
2
3
int  big = 300;
byte b   = (byte)big;    // int → byte にキャスト(300 は byte の範囲 0〜255 を超えている)
Console.WriteLine(b);   // 44 (300 % 256 = 44)

文字列 → 数値の変換

Parse メソッドを使うと文字列を数値に変換できます。

int.Parse メソッド — 文字列を int に変換する

書式:int.Parse メソッド

1
int int.Parse(string s);
パラメータ 説明
s string 整数を表す文字列
1
2
3
string s = "42";
int    i = int.Parse(s);
Console.WriteLine(i + 1);  // 43

数値に変換できない文字列を渡すと実行時に例外が発生します(例外の扱いは後のページで学びます)。

1
int.Parse("abc");  // ❌ 実行時例外: 入力文字列が正しい形式ではありません

数値 → 文字列の変換

ToString メソッドで数値を文字列に変換できます。ただし後述の文字列補間 $"..." を使う方が読みやすい場面が多いです。

1
2
int    score = 100;
string s     = score.ToString();  // "100"

6. 異なる型の演算

数値型の昇格

整数と浮動小数点数を混ぜて演算すると、より広い型に自動的に変換されてから計算されます。これを型の昇格(numeric promotion) と呼びます。

1
2
3
4
int    i      = 5;
double d      = 1.5;
var    result = i + d;        // result は double 型
Console.WriteLine(result);    // 6.5

主な数値昇格の組み合わせ:

演算の組み合わせ 結果の型
int ± int int
int ± long long
int ± float float
int ± double double
float ± double double

💡 ポイント: 「より精度の高い・範囲の広い型に合わせる」と覚えましょう。

string と数値の + 演算

string に数値を + で結合すると、数値が文字列に変換されてから連結されます。

1
2
3
int    score   = 100;
string message = "スコア: " + score;
Console.WriteLine(message);  // スコア: 100

ただし、+左から右に評価されるため、意図しない結果になることがあります。

1
2
Console.WriteLine("1 + 2 = " + 1 + 2);    // ❌ "1 + 2 = 12"
Console.WriteLine("1 + 2 = " + (1 + 2));  // ✅ "1 + 2 = 3"

"文字列" + 1"文字列1" になり、さらに + 2"文字列12" になります。数値計算はカッコで先に計算してから連結しましょう。


ワンポイントアドバイス

文字列補間 $"..." — 文字列の中に式を {式} で埋め込めます。+ で連結するより読みやすく、計算の優先順位の問題も起きません。

1
2
3
4
int    score = 100;
string name  = "Alice";
Console.WriteLine($"{name} のスコアは {score} 点です。");  // Alice のスコアは 100 点です。
Console.WriteLine($"1 + 2 = {1 + 2}");                    // 1 + 2 = 3

{式} の部分が評価され、その結果が文字列として埋め込まれます。


よくあるミス

float リテラルに f を付け忘れる

1
2
float speed = 1.5;   // ❌ コンパイルエラー: double を float に暗黙的に変換できない
float speed = 1.5f;  // ✅ OK

キャストが切り捨てだと知らずに使う

1
2
int i = (int)3.9;
Console.WriteLine(i);  // 3 (3.9 ではなく 3)

四捨五入したい場合は Math.Round を使います。

1
2
int i = (int)Math.Round(3.9);
Console.WriteLine(i);  // ✅ 4

charstring のリテラルを混同する

1
2
char c = "A";   // ❌ コンパイルエラー: string を char に代入できない
char c = 'A';   // ✅ OK

string の + で計算結果が変わる

1
2
Console.WriteLine("合計: " + 3 + 4);    // ❌ "合計: 34"
Console.WriteLine("合計: " + (3 + 4));  // ✅ "合計: 7"

まとめ


理解度チェック

  1. intuint の違いを説明してください。また、同じ32ビットでも最大値が異なるのはなぜですか?

  2. 次のコードの出力結果を答えてください。

    1
    2
    3
    
    double d = 9.9;
    int    i = (int)d;
    Console.WriteLine(i);
    
  3. 次のコードの出力結果を答えてください。

    1
    2
    
    Console.WriteLine("答えは " + 3 + 4);
    Console.WriteLine("答えは " + (3 + 4));
    
  4. 次のコードにはコンパイルエラーがあります。どこを修正すればよいですか?

    1
    
    float speed = 5.0;
    
解答を見る
  1. int は負の数も扱える(符号あり)、uint は 0 以上の値しか扱えない(符号なし)。32ビットで表現できる値の個数(2³² ≈ 42 億通り)は同じだが、int はその半分を負の数に使うため正の最大値が小さくなる。uint.MaxValue(約 42 億)は int.MaxValue(約 21 億)の約2倍。

  2. 9(int) キャストは小数点以下を切り捨てるため、9.99 になる。四捨五入ではない点に注意。

  3. 1行目は 答えは 34"答えは " + 3"答えは 3"、さらに + 4"答えは 34" と左から評価される)、2行目は 答えは 7(カッコ内の 3 + 4 = 7 を先に計算してから連結)。

  4. 5.0double リテラルなので float 型の変数には代入できない。f サフィックスを付ける。

    1
    
    float speed = 5.0f;
    

次のステップ

[条件分岐(準備中)] では、条件によって実行する処理を変える方法を学びます。