C#の型とは?基本データ型・参照型・値型の違いを初心者向けに解説
はじめに
C#を学び始めると、最初のうちに必ず出てくるのが「型」という考え方です。
たとえば、次のようなコードを見たことがあるかもしれません。
C#int age = 20;
string name = "Taro";
bool isActive = true;
ここで使われている int、string、bool が「型」です。C#では、変数にどのような種類のデータを入れるのかを型によって決めます。
C#の型を理解すると、変数の使い方、計算の仕組み、エラーの原因、値型と参照型の違い、nullの扱いなどがわかりやすくなります。この記事では、C#の型について、基本データ型、値型、参照型、型変換、Nullable型まで初心者向けに順番に解説します。
1. C#の型とは?初心者向けにわかりやすく解説
1-1. 型とは「データの種類」を決める仕組み
型とは、データの種類を表す仕組みです。
C#では、数値、文字列、真偽値、日付など、扱うデータの種類ごとに型が用意されています。
C#int count = 10;
double price = 1200.5;
string message = "こんにちは";
bool isLogin = false;
この例では、それぞれ次のような意味になります。
| 型 | 意味 |
|---|---|
| int | 整数を扱う型 |
| double | 小数を扱う型 |
| string | 文字列を扱う型 |
| bool | trueまたはfalseを扱う型 |
型を指定することで、「この変数には整数を入れる」「この変数には文字列を入れる」といったルールをC#に伝えることができます。
1-2. C#で型が重要な理由
C#で型が重要な理由は、プログラムの安全性とわかりやすさを高めるためです。
たとえば、年齢を表す変数に文字列を入れてしまうと、計算ができなくなります。
C#int age = 20;
このように int 型で宣言しておけば、age には整数を入れるものだと明確になります。
一方、次のようなコードはエラーになります。
C#int age = "20";
"20" は文字列なので、整数型の int にはそのまま代入できません。
このように、C#の型は「間違ったデータの使い方」を防ぐ役割を持っています。
1-3. 型を理解するとできるようになること
C#の型を理解すると、次のようなことができるようになります。
| できること | 内容 |
|---|---|
| 変数を正しく使える | データに合った型を選べる |
| エラーの原因がわかる | 型の不一致によるエラーを理解できる |
| 値型と参照型の違いがわかる | 代入やメソッド引数の動きを理解できる |
| nullを安全に扱える | NullReferenceExceptionを避けやすくなる |
| 型変換ができる | 文字列から数値への変換などができる |
C#の型は、初心者が最初につまずきやすい部分ですが、ここを理解するとC#全体の理解が一気に進みます。
2. C#の型の基本:静的型付けと型安全
2-1. C#は静的型付け言語
C#は静的型付け言語です。
静的型付けとは、変数や式の型がコンパイル時に決まる仕組みのことです。
C#int number = 100;
string text = "C#";
この場合、number は int 型、text は string 型として扱われます。一度 int 型として宣言した変数に、あとから文字列をそのまま入れることはできません。
C#int number = 100;
number = "abc"; // エラー
C#では、プログラムを実行する前のコンパイル時点で、型の間違いをチェックしてくれます。
2-2. 型安全とは何か
型安全とは、型のルールを守ることで、不正なデータ操作を防ぐ仕組みです。
たとえば、数値として扱うべきデータに文字列を入れたり、存在しないメソッドを呼び出したりするミスを防ぎます。
C#int x = 10;
int y = 20;
int result = x + y;
このコードでは、x と y がどちらも int 型なので、足し算ができます。
一方、次のようなコードは型が合わないためエラーになります。
C#int x = 10;
string y = "20";
int result = x + y; // エラー
型安全な仕組みによって、実行前に間違いに気づきやすくなります。
2-3. コンパイル時にエラーを発見できるメリット
C#では、型の不一致があるとコンパイル時にエラーになります。
これは初心者にとっても大きなメリットです。なぜなら、プログラムを実行してから不具合に気づくのではなく、実行前に間違いを修正できるからです。
C#int score = "100"; // コンパイルエラー
このコードは、int 型に文字列を代入しているためエラーになります。
正しく書くなら、次のようにします。
C#int score = 100;
または、文字列を数値に変換します。
C#int score = int.Parse("100");
C#の型は、コードの安全性を高め、バグを減らすための重要な仕組みです。
3. C#の基本データ型一覧
3-1. 整数型:int・long・short・byte
整数型は、小数点を含まない数値を扱う型です。
C#でよく使う整数型には、int、long、short、byte があります。
| 型 | 扱える値の例 | 特徴 |
|---|---|---|
| byte | 0〜255 | 小さな正の整数 |
| short | -32768〜32767 | 小さめの整数 |
| int | 約-21億〜約21億 | 最もよく使う整数型 |
| long | 非常に大きな整数 | 大きな数値を扱う |
通常の整数には int を使うことが多いです。
C#int age = 25;
int count = 100;
より大きな整数を扱う場合は long を使います。
C#long population = 125000000L;
long の値には、末尾に L を付けることがあります。
3-2. 小数型:float・double・decimal
小数を扱う型には、float、double、decimal があります。
| 型 | 特徴 | 主な用途 |
|---|---|---|
| float | 精度が低め | 軽量な小数計算 |
| double | 一般的な小数型 | 科学計算、通常の小数 |
| decimal | 精度が高い | 金額計算 |
C#で小数を扱う場合、一般的には double を使います。
C#double temperature = 36.5;
float を使う場合は、値の末尾に f を付けます。
C#float rate = 1.5f;
金額のように誤差を避けたい計算では decimal を使います。
C#decimal price = 1200.50m;
decimal の値には、末尾に m を付けます。
3-3. 文字・文字列型:char・string
C#で文字を扱う型には、char と string があります。
char は1文字を扱う型です。
C#char grade = 'A';
char ではシングルクォーテーション ' を使います。
一方、string は複数の文字からなる文字列を扱う型です。
C#string name = "Yamada";
string message = "こんにちは";
string ではダブルクォーテーション " を使います。
C#char c = 'A';
string text = "A";
見た目は似ていますが、char と string は別の型です。
3-4. 真偽値型:bool
bool は、true または false を扱う型です。
C#bool isLogin = true;
bool hasError = false;
条件分岐でよく使われます。
C#bool isAdult = true;
if (isAdult)
{
Console.WriteLine("成人です");
}
bool 型は、「はい/いいえ」「有効/無効」「成功/失敗」のような状態を表すときに便利です。
3-5. 日付や時刻を扱うDateTime
C#で日付や時刻を扱う場合は、DateTime 型を使います。
C#DateTime today = DateTime.Now;
Console.WriteLine(today);
特定の日付を作ることもできます。
C#DateTime birthday = new DateTime(2000, 1, 1);
年、月、日を指定して DateTime の値を作成できます。
C#Console.WriteLine(birthday.Year);
Console.WriteLine(birthday.Month);
Console.WriteLine(birthday.Day);
日付計算にも使えます。
C#DateTime tomorrow = DateTime.Now.AddDays(1);
3-6. よく使う基本データ型の選び方
初心者は、まず次の基準で型を選ぶとわかりやすいです。
| 扱いたいデータ | 選ぶ型 |
|---|---|
| 整数 | int |
| 大きな整数 | long |
| 小数 | double |
| 金額 | decimal |
| 文字列 | string |
| 1文字 | char |
| true / false | bool |
| 日付・時刻 | DateTime |
迷ったときは、整数なら int、小数なら double、文字列なら string、真偽値なら bool を使うとよいでしょう。
4. C#の値型とは?
4-1. 値型の特徴
値型とは、変数そのものが値を持つ型です。
代表的な値型には、int、double、bool、char、DateTime などがあります。
C#int a = 10;
int b = a;
この場合、b には a の値である 10 がコピーされます。
その後、b を変更しても a には影響しません。
C#int a = 10;
int b = a;
b = 20;
Console.WriteLine(a); // 10
Console.WriteLine(b); // 20
値型では、代入時に値がコピーされると考えると理解しやすいです。
4-2. 値型に分類される主な型
C#の主な値型には、次のようなものがあります。
| 分類 | 型 |
|---|---|
| 整数型 | byte, short, int, long |
| 小数型 | float, double, decimal |
| 文字型 | char |
| 真偽値型 | bool |
| 日付型 | DateTime |
| 構造体 | struct |
| 列挙型 | enum |
基本データ型の多くは値型です。
ただし、string はよく使う基本的な型ですが、値型ではなく参照型です。
4-3. 値型の代入時の動き
値型を別の変数に代入すると、値がコピーされます。
C#int x = 5;
int y = x;
y = 10;
Console.WriteLine(x); // 5
Console.WriteLine(y); // 10
y = x; の時点で、x の値が y にコピーされます。そのため、あとから y を変更しても x は変わりません。
これは値型の重要な特徴です。
4-4. structとenumの基本
C#では、自分で値型を定義することもできます。その代表が struct と enum です。
struct は構造体と呼ばれ、複数のデータをまとめる値型です。
C#struct Point
{
public int X;
public int Y;
}
使うときは次のように書きます。
C#Point p;
p.X = 10;
p.Y = 20;
enum は列挙型と呼ばれ、決まった選択肢を名前で表す型です。
C#enum OrderStatus
{
Pending,
Shipped,
Delivered
}
使うときは次のように書きます。
C#OrderStatus status = OrderStatus.Shipped;
enum を使うと、数値だけで状態を表すよりもコードが読みやすくなります。
4-5. 値型で注意したいポイント
値型で注意したいのは、通常は null を代入できないことです。
C#int number = null; // エラー
int は値型なので、通常は必ず何らかの数値を持ちます。
ただし、Nullable型を使えば、値型でも null を扱えます。
C#int? number = null;
また、値型は代入時にコピーされるため、大きな構造体を頻繁にコピーするとパフォーマンスに影響する場合があります。初心者のうちは、まず「値型は値がコピーされる」と理解しておけば十分です。
5. C#の参照型とは?
5-1. 参照型の特徴
参照型とは、データそのものではなく、データがある場所への参照を持つ型です。
代表的な参照型には、class、string、配列、object などがあります。
C#class Person
{
public string Name;
}
参照型の変数には、オブジェクトそのものではなく、オブジェクトを指す参照が入っていると考えるとわかりやすいです。
C#Person p1 = new Person();
p1.Name = "Taro";
Person p2 = p1;
p2.Name = "Hanako";
Console.WriteLine(p1.Name); // Hanako
p1 と p2 は同じオブジェクトを参照しているため、p2.Name を変更すると p1.Name も変わったように見えます。
5-2. 参照型に分類される主な型
C#の主な参照型には、次のようなものがあります。
| 分類 | 型 |
|---|---|
| クラス | class |
| 文字列 | string |
| 配列 | int[], string[] など |
| object型 | object |
| インターフェイス | interface |
| デリゲート | delegate |
C#で作成する多くのオブジェクトは参照型です。
C#string name = "Taro";
int[] numbers = { 1, 2, 3 };
object value = 100;
string は特別な動きをするため値型のように見えることがありますが、分類としては参照型です。
5-3. 参照型の代入時の動き
参照型を代入すると、オブジェクトそのものではなく参照がコピーされます。
C#Person a = new Person();
a.Name = "Taro";
Person b = a;
b.Name = "Jiro";
Console.WriteLine(a.Name); // Jiro
Console.WriteLine(b.Name); // Jiro
a と b は同じオブジェクトを参照しています。そのため、片方から中身を変更すると、もう片方から見ても変更後の値になります。
ただし、別のオブジェクトを代入すると参照先が変わります。
C#b = new Person();
b.Name = "Saburo";
Console.WriteLine(a.Name); // Jiro
Console.WriteLine(b.Name); // Saburo
参照型では、「変数が何を指しているか」を意識することが大切です。
5-4. class・string・arrayの基本
class は、C#でオブジェクトを定義するための基本的な仕組みです。
C#class User
{
public string Name;
public int Age;
}
使うときは new を使ってインスタンスを作成します。
C#User user = new User();
user.Name = "Yamada";
user.Age = 30;
string は文字列を扱う参照型です。
C#string message = "Hello";
配列も参照型です。
C#int[] numbers = { 1, 2, 3 };
numbers[0] = 10;
Console.WriteLine(numbers[0]); // 10
配列を別の変数に代入すると、同じ配列を参照します。
C#int[] a = { 1, 2, 3 };
int[] b = a;
b[0] = 100;
Console.WriteLine(a[0]); // 100
5-5. null参照に注意する理由
参照型の変数には、オブジェクトを参照していない状態である null が入ることがあります。
C#Person person = null;
この状態でメンバーにアクセスすると、実行時エラーになります。
C#Console.WriteLine(person.Name); // NullReferenceException
このエラーは、C#初心者がよく遭遇する代表的なエラーです。
対策としては、使用前に null チェックを行います。
C#if (person != null)
{
Console.WriteLine(person.Name);
}
また、C#ではNullable参照型を使うことで、nullの可能性をコード上で明確にできます。
6. 値型と参照型の違い
6-1. データの保存場所の違い
値型と参照型の違いを理解するうえで大切なのが、データの持ち方です。
値型は、変数が値そのものを持ちます。
C#int x = 10;
参照型は、変数がオブジェクトへの参照を持ちます。
C#Person p = new Person();
厳密なメモリ管理の詳細は状況によって異なりますが、初心者の段階では次のように理解するとよいです。
| 種類 | イメージ |
|---|---|
| 値型 | 変数の中に値そのものがある |
| 参照型 | 変数の中にデータの場所を示す情報がある |
6-2. 代入時の動きの違い
値型では、代入すると値がコピーされます。
C#int a = 10;
int b = a;
b = 20;
Console.WriteLine(a); // 10
参照型では、代入すると参照がコピーされます。
C#Person p1 = new Person();
p1.Name = "Taro";
Person p2 = p1;
p2.Name = "Jiro";
Console.WriteLine(p1.Name); // Jiro
値型は別々の値になりますが、参照型は同じオブジェクトを指すことがあります。
6-3. メソッド引数に渡したときの違い
値型をメソッドに渡すと、通常は値がコピーされます。
C#void ChangeNumber(int x)
{
x = 100;
}
int number = 10;
ChangeNumber(number);
Console.WriteLine(number); // 10
メソッド内で x を変更しても、元の number は変わりません。
一方、参照型を渡すと、参照がコピーされます。オブジェクトの中身を変更すると、呼び出し元にも影響します。
C#void ChangeName(Person person)
{
person.Name = "Hanako";
}
Person p = new Person();
p.Name = "Taro";
ChangeName(p);
Console.WriteLine(p.Name); // Hanako
ただし、メソッド内で引数そのものに別のオブジェクトを代入しても、通常は呼び出し元の変数の参照先は変わりません。
6-4. nullを扱えるかどうかの違い
参照型は通常 null を扱えます。
C#string name = null;
一方、値型は通常 null を扱えません。
C#int number = null; // エラー
値型で null を扱いたい場合は、Nullable型を使います。
C#int? number = null;
この違いは、C#の型を理解するうえで非常に重要です。
6-5. 値型と参照型の違いを表で比較
| 比較項目 | 値型 | 参照型 |
|---|---|---|
| データの持ち方 | 値そのものを持つ | オブジェクトへの参照を持つ |
| 代表例 | int, double, bool, DateTime, struct, enum | class, string, array, object |
| 代入時の動き | 値がコピーされる | 参照がコピーされる |
| null | 通常は代入できない | 代入できる |
| 変更の影響 | コピー先を変更しても元に影響しにくい | 同じオブジェクトなら影響する |
| 初心者が注意する点 | コピーされること | 同じ参照を共有すること |
値型と参照型の違いは、C#の型の中でも特に重要です。配列やクラスを扱うようになると、この違いを理解しているかどうかでコードの読みやすさが大きく変わります。
7. C#の型推論:varの使い方
7-1. varとは何か
var は、右辺の値から型を自動的に推論するためのキーワードです。
C#var number = 10;
var name = "Taro";
var isActive = true;
この場合、C#は次のように型を判断します。
| コード | 推論される型 |
|---|---|
| var number = 10; | int |
| var name = "Taro"; | string |
| var isActive = true; | bool |
var を使うと型を書かなくても変数を宣言できます。
7-2. varを使っても型は決まっている
var を使っても、型がなくなるわけではありません。
C#var number = 10;
この時点で、number は int 型として決まります。
そのため、あとから文字列を代入することはできません。
C#var number = 10;
number = "abc"; // エラー
var は「何でも入れられる型」ではなく、「コンパイラが型を推論してくれる書き方」です。
7-3. varを使うメリット
var を使うメリットは、コードを簡潔に書けることです。
C#Dictionary<string, int> scores = new Dictionary<string, int>();
このような長い型名は、var を使うと短くできます。
C#var scores = new Dictionary<string, int>();
右辺を見れば型が明らかな場合、var を使うとコードが読みやすくなることがあります。
また、LINQなどを使う場面でも var はよく使われます。
C#var result = numbers.Where(n => n > 10);
7-4. varを使うときの注意点
var は便利ですが、使いすぎると型がわかりにくくなることがあります。
C#var data = GetData();
このコードだけを見ると、data が何の型なのかわかりにくいです。
一方、次のように右辺から型が明らかな場合は読みやすいです。
C#var user = new User();
初心者のうちは、型を理解する練習のために、あえて明示的に型を書くのもおすすめです。
C#int count = 10;
string name = "Taro";
bool isActive = true;
型に慣れてきたら、読みやすさを考えて var を使い分けるとよいでしょう。
7-5. varとdynamicの違い
var と dynamic は似ているように見えますが、まったく違います。
var はコンパイル時に型が決まります。
C#var x = 10;
x = "abc"; // エラー
一方、dynamic は実行時に型が判断されます。
C#dynamic y = 10;
y = "abc"; // OK
dynamic は柔軟ですが、実行するまでエラーに気づけないことがあります。
C#dynamic value = "hello";
Console.WriteLine(value.NotExistMethod()); // 実行時エラー
初心者はまず var と通常の型指定を中心に使い、dynamic は必要な場面だけに限定するのがおすすめです。
8. C#のobject型・dynamic型とは?
8-1. object型とはすべての型の基底型
object 型は、C#のすべての型の基底となる型です。
つまり、int、string、bool、クラスのインスタンスなど、さまざまな値を object 型の変数に代入できます。
C#object a = 10;
object b = "Hello";
object c = true;
ただし、object 型として扱うと、元の型に固有の操作をそのまま使えない場合があります。
C#object value = "Hello";
// value.Length はそのままでは使えない
string として扱いたい場合は、キャストが必要です。
C#object value = "Hello";
string text = (string)value;
Console.WriteLine(text.Length);
8-2. dynamic型とは実行時に型を判定する型
dynamic 型は、コンパイル時ではなく実行時に型のチェックを行う型です。
C#dynamic value = "Hello";
Console.WriteLine(value.Length);
このコードはコンパイルできます。value は実行時に文字列として扱われ、Length プロパティにアクセスできます。
しかし、存在しないメソッドを呼び出してもコンパイル時にはエラーになりません。
C#dynamic value = "Hello";
value.NotExistMethod(); // 実行時エラー
dynamic は便利な場面もありますが、型安全性が下がるため注意が必要です。
8-3. objectとdynamicの違い
object と dynamic は、どちらもさまざまな型の値を入れられます。
しかし、メンバーへのアクセス方法に違いがあります。
C#object obj = "Hello";
// Console.WriteLine(obj.Length); // コンパイルエラー
dynamic dyn = "Hello";
Console.WriteLine(dyn.Length); // 実行時に解決
比較すると次のようになります。
| 項目 | object | dynamic |
|---|---|---|
| 型チェック | コンパイル時 | 実行時 |
| 安全性 | 高い | 低くなりやすい |
| キャスト | 必要な場合が多い | 不要に見える |
| エラー発見 | 早い | 実行時まで遅れることがある |
object は型の基礎として重要ですが、実際に使うときはキャストや型判定が必要になることが多いです。
8-4. 初心者がdynamicを多用しないほうがよい理由
初心者が dynamic を多用しないほうがよい理由は、C#の大きなメリットである型安全性を活かしにくくなるからです。
通常のC#では、型の間違いをコンパイル時に見つけられます。
C#string text = "Hello";
Console.WriteLine(text.NotExistMethod()); // コンパイルエラー
しかし dynamic を使うと、コンパイル時にはエラーにならず、実行時にエラーになります。
C#dynamic text = "Hello";
Console.WriteLine(text.NotExistMethod()); // 実行時エラー
初心者のうちは、int、string、bool、DateTime、自作クラスなど、明確な型を使ってコードを書くほうが学習しやすいです。
9. Nullable型とは?nullを扱うための型
9-1. Nullable型の基本
Nullable型とは、通常は null を入れられない値型に null を入れられるようにする仕組みです。
たとえば、int 型には通常 null を代入できません。
C#int age = null; // エラー
しかし、int? と書くと null を扱えるようになります。
C#int? age = null;
int? は、正式には Nullable<int> と同じ意味です。
C#Nullable<int> age = null;
9-2. int?やbool?の使い方
Nullable型は、値が未設定の場合を表したいときに便利です。
C#int? age = null;
bool? isMember = null;
値があるかどうかは HasValue で確認できます。
C#int? age = 20;
if (age.HasValue)
{
Console.WriteLine(age.Value);
}
ただし、Value を使うときは、値が入っていることを確認してから使う必要があります。
C#int? age = null;
// Console.WriteLine(age.Value); // エラーの原因になる
9-3. null合体演算子との組み合わせ
Nullable型では、null合体演算子 ?? がよく使われます。
?? は、左辺が null の場合に右辺の値を使う演算子です。
C#int? age = null;
int displayAge = age ?? 0;
Console.WriteLine(displayAge); // 0
age が null でなければ、その値が使われます。
C#int? age = 25;
int displayAge = age ?? 0;
Console.WriteLine(displayAge); // 25
文字列でも同じように使えます。
C#string name = null;
string displayName = name ?? "未設定";
Console.WriteLine(displayName); // 未設定
9-4. Nullable参照型の考え方
C#には、Nullable参照型という考え方もあります。
これは、参照型に対して「nullになる可能性があるかどうか」を明確にする仕組みです。
C#string name = "Taro";
string? nickname = null;
string はnullを想定しない文字列、string? はnullの可能性がある文字列として扱います。
Nullable参照型を有効にすると、nullの可能性がある変数を安全に扱うようにコンパイラが警告してくれます。
C#string? name = null;
// 警告が出る可能性がある
Console.WriteLine(name.Length);
安全に書くなら、nullチェックをします。
C#if (name != null)
{
Console.WriteLine(name.Length);
}
Nullable参照型は、nullによるエラーを減らすために役立ちます。
10. 型変換の基本
10-1. 暗黙的な型変換
暗黙的な型変換とは、自動的に行われる型変換のことです。
小さい範囲の型から大きい範囲の型へ変換する場合など、安全に変換できるときに使われます。
C#int number = 100;
long bigNumber = number;
int の値は long に安全に入れられるため、自動的に変換されます。
C#int x = 10;
double y = x;
この場合も、int から double へ暗黙的に変換されます。
10-2. 明示的な型変換
明示的な型変換とは、キャストを使って型を変換する方法です。
大きい範囲の型から小さい範囲の型へ変換する場合など、データが失われる可能性があるときに必要です。
C#double x = 10.5;
int y = (int)x;
Console.WriteLine(y); // 10
小数部分は切り捨てられます。
また、long から int への変換も明示的なキャストが必要です。
C#long bigNumber = 1000;
int number = (int)bigNumber;
ただし、値が変換先の範囲を超えている場合は、予期しない結果やエラーの原因になることがあります。
10-3. Parse・TryParse・Convertの違い
文字列を数値に変換する場合、Parse、TryParse、Convert がよく使われます。
Parse は、変換できない文字列を渡すと例外が発生します。
C#int number = int.Parse("123");
次のような場合はエラーになります。
C#int number = int.Parse("abc"); // 例外
TryParse は、変換に成功したかどうかを bool で返します。
C#string text = "123";
if (int.TryParse(text, out int number))
{
Console.WriteLine(number);
}
else
{
Console.WriteLine("変換できません");
}
Convert は、さまざまな型変換に使える便利なクラスです。
C#int number = Convert.ToInt32("123");
ただし、変換できない文字列では例外が発生します。
初心者には、安全に変換しやすい TryParse がおすすめです。
10-4. 型変換で起こりやすいエラー
型変換でよくあるエラーは、変換できない文字列を数値に変換しようとするケースです。
C#int number = int.Parse("abc"); // エラー
また、小数の文字列を整数に変換しようとして失敗することもあります。
C#int number = int.Parse("10.5"); // エラー
この場合は、まず double として変換する必要があります。
C#double number = double.Parse("10.5");
また、数値の範囲を超える変換にも注意が必要です。
C#long bigNumber = 9999999999;
int number = (int)bigNumber; // 注意
10-5. 安全に型変換するコツ
安全に型変換するには、次のポイントを意識しましょう。
| ポイント | 内容 |
|---|---|
| ユーザー入力はTryParseを使う | 不正な入力でも例外を防ぎやすい |
| 小数と整数を区別する | intとdoubleを混同しない |
| 範囲に注意する | longからintなどは値の範囲を確認する |
| nullに注意する | nullを変換しようとしない |
| 必要以上にキャストしない | 型を明確に設計する |
特に、画面やファイルから読み込んだ文字列を数値に変換するときは、TryParse を使うと安全です。
C#string input = "100";
if (int.TryParse(input, out int result))
{
Console.WriteLine(result);
}
else
{
Console.WriteLine("数値ではありません");
}
11. 型を調べる方法
11-1. typeofの使い方
typeof は、型そのものの情報を取得するために使います。
C#Console.WriteLine(typeof(int));
Console.WriteLine(typeof(string));
Console.WriteLine(typeof(bool));
実行すると、型の名前が表示されます。
typeof は、型名を直接指定して使います。
C#Type type = typeof(int);
Console.WriteLine(type.Name); // Int32
int はC#での書き方で、実際の.NET上では System.Int32 として扱われます。
11-2. GetTypeの使い方
GetType は、実際のオブジェクトの型を調べるために使います。
C#int number = 10;
Console.WriteLine(number.GetType());
文字列でも使えます。
C#string name = "Taro";
Console.WriteLine(name.GetType());
typeof は型名から型情報を取得し、GetType は変数やオブジェクトから型情報を取得する、と考えるとわかりやすいです。
C#Console.WriteLine(typeof(string));
string text = "Hello";
Console.WriteLine(text.GetType());
11-3. is演算子で型を判定する
is 演算子を使うと、あるオブジェクトが特定の型かどうかを判定できます。
C#object value = "Hello";
if (value is string)
{
Console.WriteLine("string型です");
}
型判定と同時に変数へ代入することもできます。
C#object value = "Hello";
if (value is string text)
{
Console.WriteLine(text.Length);
}
この書き方を使うと、キャストを安全に行いやすくなります。
11-4. as演算子で安全にキャストする
as 演算子は、参照型のキャストに使います。
キャストに成功するとその型の値を返し、失敗すると null を返します。
C#object value = "Hello";
string text = value as string;
if (text != null)
{
Console.WriteLine(text.Length);
}
通常のキャストでは、失敗すると例外が発生します。
C#object value = 123;
// string text = (string)value; // 例外
as を使うと、失敗時に null になるため、安全に判定できます。
ただし、値型には基本的に as は使えません。値型で安全に判定したい場合は、is を使うことが多いです。
12. C#の型で初心者がつまずきやすいポイント
12-1. intとdoubleの計算結果が想定と違う
C#では、整数同士の割り算は整数になります。
C#int a = 5;
int b = 2;
Console.WriteLine(a / b); // 2
5 / 2 は本来 2.5 ですが、int 同士の計算なので小数部分が切り捨てられます。
小数として計算したい場合は、どちらかを double にします。
C#double result = 5.0 / 2;
Console.WriteLine(result); // 2.5
または、キャストします。
C#int a = 5;
int b = 2;
double result = (double)a / b;
Console.WriteLine(result); // 2.5
12-2. stringは参照型だが特別な動きをする
string は参照型ですが、値型のように見えることがあります。
C#string a = "Hello";
string b = a;
b = "World";
Console.WriteLine(a); // Hello
Console.WriteLine(b); // World
参照型なら同じオブジェクトを共有しているように見えますが、string は変更できない性質を持っています。これをイミュータブルといいます。
文字列を変更したように見えても、実際には新しい文字列が作られます。
C#string text = "Hello";
text = text + " C#";
この場合、元の文字列を直接変更しているのではなく、新しい文字列を text に代入しています。
12-3. nullを入れられる型と入れられない型がある
C#では、型によって null を入れられるかどうかが異なります。
C#string name = null; // 参照型なので可能
int number = null; // 値型なのでエラー
値型で null を扱いたい場合は、? を付けます。
C#int? number = null;
bool? flag = null;
参照型でも、Nullable参照型を有効にしている場合は、string と string? を区別します。
C#string name = "Taro";
string? nickname = null;
nullを扱うときは、「この変数はnullになる可能性があるか」を意識することが重要です。
12-4. varは何でも入れられる型ではない
var を使うと型を書かずに変数宣言できますが、何でも入れられるわけではありません。
C#var number = 10;
number = 20; // OK
number = "abc"; // エラー
最初に 10 を代入した時点で、number は int 型に決まります。
つまり、次のコードと同じ意味です。
C#int number = 10;
var は型を省略しているだけで、型が存在しないわけではありません。
12-5. 型変換とキャストを混同しない
型変換とキャストは似ていますが、意味が少し違います。
キャストは、型を明示して変換する書き方です。
C#double x = 10.5;
int y = (int)x;
一方、文字列を数値に変換する場合は、キャストではなく Parse や TryParse を使います。
C#string text = "123";
int number = int.Parse(text);
次のような書き方はできません。
C#string text = "123";
// int number = (int)text; // エラー
文字列から数値に変換する場合は、int.Parse、int.TryParse、Convert.ToInt32 などを使いましょう。
13. C#の型を理解するための練習例
13-1. 変数宣言で型を確認する
まずは、基本的な型で変数を宣言してみましょう。
C#int age = 20;
double height = 170.5;
string name = "Taro";
bool isStudent = true;
DateTime today = DateTime.Now;
Console.WriteLine(age);
Console.WriteLine(height);
Console.WriteLine(name);
Console.WriteLine(isStudent);
Console.WriteLine(today);
この練習では、どのデータにどの型を使うのかを確認できます。
次のように、あえて間違った型を代入してみると、C#がコンパイル時にエラーを出してくれることも確認できます。
C#// int age = "20"; // エラー
// bool isStudent = "true"; // エラー
13-2. 値型と参照型の代入の違いを確認する
値型の代入を確認してみましょう。
C#int a = 10;
int b = a;
b = 20;
Console.WriteLine(a); // 10
Console.WriteLine(b); // 20
次に、参照型の代入を確認します。
C#class Person
{
public string Name;
}
Person p1 = new Person();
p1.Name = "Taro";
Person p2 = p1;
p2.Name = "Hanako";
Console.WriteLine(p1.Name); // Hanako
Console.WriteLine(p2.Name); // Hanako
この2つを比べると、値型は値がコピーされ、参照型は同じオブジェクトを参照することがわかります。
13-3. 型変換を試してみる
文字列から数値への変換を試してみましょう。
C#string text = "100";
int number = int.Parse(text);
Console.WriteLine(number + 50); // 150
次に、TryParse を使って安全に変換します。
C#string input = "abc";
if (int.TryParse(input, out int result))
{
Console.WriteLine(result);
}
else
{
Console.WriteLine("数値に変換できません");
}
ユーザー入力や外部データを扱う場合は、TryParse を使うとエラーを防ぎやすくなります。
13-4. typeofとGetTypeで型を表示する
最後に、型を調べる練習をしてみましょう。
C#Console.WriteLine(typeof(int));
Console.WriteLine(typeof(string));
変数から型を調べる場合は GetType を使います。
C#int number = 10;
string text = "Hello";
bool flag = true;
Console.WriteLine(number.GetType());
Console.WriteLine(text.GetType());
Console.WriteLine(flag.GetType());
var を使った場合も、実際の型を確認できます。
C#var value = 123;
Console.WriteLine(value.GetType()); // System.Int32
var を使っても、C#では型がしっかり決まっていることがわかります。
まとめ
C#の型とは、データの種類を決めるための仕組みです。C#では、変数を使うときに int、string、bool、double などの型を指定し、どのようなデータを扱うのかを明確にします。
C#は静的型付け言語であり、型の間違いをコンパイル時に発見できます。そのため、型を正しく理解することは、エラーの少ない安全なコードを書くうえで非常に重要です。
基本データ型には、整数を扱う int、小数を扱う double や decimal、文字列を扱う string、真偽値を扱う bool、日付を扱う DateTime などがあります。
また、C#の型は大きく値型と参照型に分けられます。値型は値そのものを持ち、代入時には値がコピーされます。参照型はオブジェクトへの参照を持ち、代入時には参照がコピーされます。この違いを理解すると、変数の代入やメソッド引数の動きがわかりやすくなります。
var は型推論によって型を自動で決める便利な機能ですが、何でも入れられる型ではありません。object や dynamic も柔軟な型ですが、特に dynamic は実行時エラーにつながりやすいため、多用しすぎないことが大切です。
さらに、int? のようなNullable型を使うと、値型でも null を扱えます。型変換では、暗黙的な型変換、明示的なキャスト、Parse、TryParse、Convert の違いを理解しておくと、実践的なコードを書きやすくなります。
C#の型は、最初は覚えることが多く感じるかもしれません。しかし、基本データ型、値型、参照型、null、型変換を順番に理解していけば、C#プログラミングの土台がしっかり身につきます。

