C#の構造体(struct)とクラスの違いを徹底解説!初心者でも分かるC#オブジェクトの基本
生徒
「C#でstruct(ストラクト)とclass(クラス)ってどう違うんですか?」
先生
「いい質問ですね!C#では、struct(構造体)とclass(クラス)は見た目は似ていますが、動き方が大きく違います。」
生徒
「えっ、どういうことですか?同じように使えると思っていました…」
先生
「それでは、初心者でも分かるように、structとclassの違いを詳しく解説していきましょう!」
1. struct(構造体)とは?
C#のstruct(構造体)は、一言でいうと「値型(バリュータイプ)」に分類されるデータ構造です。初心者の方には少し難しい言葉かもしれませんが、普段使っているint(整数)やbool(真偽値)と同じ仲間だと考えると分かりやすいでしょう。
最大の特徴は、メモリ上にデータそのものが直接保存されるという点です。そのため、変数から別の変数へ代入(コピー)を行うと、中身がまるごと複製されます。これは「オリジナルのコピーを作成して渡す」ような動きになるため、コピー先で値を書き換えても、コピー元の値には一切影響を与えません。
それでは、プログラミングが初めての方でもイメージしやすいように、身近な「試験の点数」を管理する簡単な構造体のサンプルを見てみましょう。
// テストの結果を保持する「構造体」の定義
struct TestScore
{
public int Math; // 数学の点数
public int English; // 英語の点数
}
// 実際に構造体を使ってみる
TestScore score1 = new TestScore();
score1.Math = 80;
score1.English = 70;
// score1をscore2にコピー(まるごと複製される)
TestScore score2 = score1;
score2.Math = 100; // score2の数学だけ100点に書き換え
// それぞれの結果を表示
Console.WriteLine("score1の数学: " + score1.Math);
Console.WriteLine("score2の数学: " + score2.Math);
実行結果:
score1の数学: 80
score2の数学: 100
このように、score2の値を変更してもscore1は80点のまま変わりません。これが「値型」である構造体の振る舞いです。
構造体は、今回のような「点数」や「座標(X, Y)」、「RGBの色情報」といった、少数のデータをセットで扱う小さな箱のような役割に非常に適しています。軽量で無駄が少ないため、大量のデータを高速に処理したい場面でその真価を発揮します。
2. class(クラス)とは?
一方で、C#のclass(クラス)は「参照型(リファレンスタイプ)」と呼ばれます。これは構造体とは根本的にデータの持ち方が異なります。変数の中に直接データを入れるのではなく、データの「実体」が置かれているメモリ上の住所(参照先)だけを記録する仕組みです。
身近な例でいうと、構造体が「手紙そのもの」を渡すのに対し、クラスは「情報の場所が書かれた地図」を渡すようなイメージです。そのため、クラスを別の変数にコピーしても、コピーされるのは「場所の情報」だけであり、指し示している実体は同じものになります。片方の変数を通じて中身を書き換えると、もう片方の変数から見た内容も変わってしまうのが大きな特徴です。
プログラミングが初めての方でも理解しやすいように、名前を管理する「名札」のようなクラスの動作例を見てみましょう。
// 氏名を管理する「クラス」の定義
class StudentProfile
{
public string Name; // 生徒の名前
}
// 実際にクラスを使ってみる
StudentProfile student1 = new StudentProfile();
student1.Name = "田中さん";
// student1をstudent2に代入(データの場所が共有される)
StudentProfile student2 = student1;
student2.Name = "佐藤さん"; // student2の名前を書き換える
// それぞれの結果を表示
Console.WriteLine("student1の名前: " + student1.Name);
Console.WriteLine("student2の名前: " + student2.Name);
実行結果:
student1の名前: 佐藤さん
student2の名前: 佐藤さん
実行結果を見ると、student2の名前を変えただけなのに、student1の名前まで「佐藤さん」に変わっています。これは、両方の変数がメモリ上の全く同じデータを指し示しているためです。
クラスは、このように複数の場所で同じ情報を共有したり、複雑な処理(メソッド)を組み込んだりするのに非常に適しています。C#のオブジェクト指向プログラミングにおいて、最も中心的な役割を果たすのがこのクラスです。
3. 値型と参照型の違いとは?
ここで「値型」と「参照型」の違いを、初心者向けに荷物のやりとりにたとえてみましょう。
- struct(構造体)=値型は、「荷物を直接渡す」イメージ。コピーすれば、それぞれが別の荷物を持っています。
- class(クラス)=参照型は、「荷物の保管場所のメモを渡す」ようなもの。コピーしても、実際には同じ保管場所を見ているだけです。
この違いによって、データの扱い方やパフォーマンスにも影響があります。
4. structとclassの使い分けのポイント
C#では、構造体とクラスは状況によって使い分けるのが重要です。以下のような基準を覚えておくと便利です。
- データが小さくて単純 →
struct(構造体) - データが大きくて複雑 →
class(クラス) - コピーされたときに、別のデータとして扱いたい →
struct - コピーしても、同じものを共有したい →
class
5. 実際の違いをコードで見てみよう
構造体とクラスのコピー時の違いを、サンプルプログラムで見てみましょう。
構造体(struct)の例:
struct MyStruct
{
public int Value;
}
MyStruct a = new MyStruct();
a.Value = 10;
MyStruct b = a;
b.Value = 20;
Console.WriteLine("a.Value = " + a.Value);
Console.WriteLine("b.Value = " + b.Value);
実行結果:
a.Value = 10
b.Value = 20
→ bを変更してもaは影響を受けていません。これは、structが値型だからです。
クラス(class)の例:
class MyClass
{
public int Value;
}
MyClass a = new MyClass();
a.Value = 10;
MyClass b = a;
b.Value = 20;
Console.WriteLine("a.Value = " + a.Value);
Console.WriteLine("b.Value = " + b.Value);
実行結果:
a.Value = 20
b.Value = 20
→ bを変更すると、aも変わってしまいました。これは、classが参照型で、同じデータを見ているからです。
6. その他の違いもチェックしよう
structとclassには、ほかにも次のような違いがあります。
- 継承(けいしょう):
classは他のクラスを継承できますが、structはできません。 - デフォルトコンストラクタ:
structには自分でコンストラクタを定義することはできますが、引数なしのコンストラクタは自動で作られ、変更できません。 - null(ヌル)代入:
classの変数にはnullを代入できますが、structにはできません(ただしNullable<T>型を使えば可能)。
7. 実務でよく使われるのはどっち?
実際の開発では、クラス(class)が使われることが多いです。なぜなら、アプリケーションの多くは複雑なデータを扱うため、柔軟に機能を追加できるクラスが適しているからです。
一方、構造体(struct)は、軽量で処理が早いため、ゲーム開発やグラフィック処理など、パフォーマンスが求められる場面で使われることが多いです。
まとめ
C#のstruct(構造体)とclass(クラス)は、初心者が最初につまずきやすいテーマでありながら、プログラムの設計やデータ管理を考えるうえで非常に重要な概念です。ここまでの記事で学んだように、structは値型であり、classは参照型という根本的な違いがあります。値型はデータそのものをコピーしますが、参照型はデータの位置を共有するため、同じインスタンスを触っているように動作します。この特徴を理解することで、メモリの扱い方、パフォーマンス、データの独立性などをしっかり意識したプログラムが書けるようになります。
特に、初心者が誤解しやすいのが「コピーしたら別物なのか、同じ物なのか」という点です。小さくて軽いデータを扱いたいときは構造体が役立ち、複雑で大きな処理をまとめたいときにはクラスが適しています。実務で多く使われるのはクラスですが、構造体を適切に活用することで、無駄なメモリ使用を避けたり、高速な処理を実現したりすることが可能になります。
また、structには継承ができない、classはnullを扱えるなど、それぞれ特性にも違いがあります。こういった特性を知らずに使うと不具合の原因になりやすいため、今回の内容を一度整理して、自分のアプリケーションでどちらを選ぶべきか判断できるようにすることが大切です。structとclassは見た目が似ていても目的が異なるため、役割を意識した設計が求められます。
ここで、構造体とクラスの違いを明確に理解するために、記事で学んだ内容を応用したサンプルコードをひとつ紹介します。小規模データを扱うstructと、複雑な情報を扱うclassを同時に利用することで、それぞれの特徴と用途がよりはっきりと見えてきます。
サンプルプログラム:構造体とクラスの特徴を活かしたデータ管理
下記のプログラムでは、「座標」をstructで管理し、「キャラクター情報」をclassで扱っています。ゲーム開発や業務アプリなど、さまざまな場面でこの設計はよく使われます。
struct Position
{
public int X;
public int Y;
public Position(int x, int y)
{
this.X = x;
this.Y = y;
}
}
class Character
{
public string Name;
public Position Pos;
public Character(string name, Position pos)
{
this.Name = name;
this.Pos = pos;
}
public void Move(int x, int y)
{
this.Pos.X += x;
this.Pos.Y += y;
}
public void ShowInfo()
{
Console.WriteLine("キャラクター名: " + this.Name);
Console.WriteLine("現在位置: X=" + this.Pos.X + ", Y=" + this.Pos.Y);
}
}
class Program
{
static void Main()
{
Position start = new Position(0, 0);
Character hero = new Character("勇者", start);
hero.Move(5, 3);
hero.ShowInfo();
}
}
この例では、座標のように小さく独立したデータはstructで扱い、キャラクターのように複数の情報をまとめたい場合にはclassを使うことで、データの扱いが整理され、動作の意図も分かりやすくなります。構造体はコピーされることで独立した値として扱われるため、元の値に影響を与えません。一方、クラスは参照型であるため、どこからでも同じキャラクター情報を共有できます。これが、用途に応じた適切なデータの選び方につながります。
structとclassの正しい使い分けを理解することで、コードの読みやすさや保守性が劇的に向上します。また、開発中の不具合を未然に防ぎやすくなるため、初心者だけでなく経験者にとっても重要な基礎知識です。値型と参照型の仕組みを理解したうえで、適切な場面で使い分けることが今後のC#プログラミングの上達につながります。
生徒
「structとclassって名前が似ているから同じように考えていましたが、値型と参照型でこんなに違うんですね…!」
先生
「そうなんです。特にコピーしたときの挙動が大きく違うので、どちらを使うべきか考えることが大切ですよ。」
生徒
「たしかに、structは軽くて速いけど、classは複雑なデータをまとめられるって理解できました!」
先生
「用途によって選べるようになると、プログラムの設計が一気に楽になりますよ。今回のサンプルも良い例でしたね。」
生徒
「次からは“値型か参照型か”を意識して、structとclassをちゃんと使い分けてみます!」