今回は、C#の構造体の使い方やクラスとの違いについてご紹介します。
C#の構造体とは
構造体(struct)は値型として扱われ、インスタンスが代入や引数として渡される際に実体のコピーが行われます。
このため、同じ値を別の変数で扱う場合でも、片方を変更するともう片方に影響が及ぶことはありません。
メモリ上ではスタックに配置されることが多く、ガベージコレクション(GC)の対象になりにくい点も特徴です。
ただし、構造体自体が大きくなるとコピーコストが大きくなるため、使いどころを見極める必要があります。
クラスとの違い
クラス(class)が参照型として扱われるのに対し、構造体は値型として扱われます。
クラスの場合はインスタンスの実体ではなく参照をコピーするため、変数が同じオブジェクトを共有している状態です。
そのため、一方を変更すると他の変数にも変更内容が反映されます。
また、クラスは継承やポリモーフィズムが使えますが、構造体は継承ができずインターフェースの実装のみ可能です。
基本的な使い方
構造体は以下のポイントを押さえて定義することが多いです。
- 値型であるため、不変(immutable)設計が推奨
- 読み取り専用プロパティを使うと、誤った変更を防げる
- C# 10以降ではパラメータなしコンストラクタも定義可能
- 大きな構造体ではコピーコストの増大に注意
また、クラスと比較してメモリ配置やパフォーマンス特性が異なるため、用途に合わせて選択することが重要です。
実用的な具体例
次の例では、2次元座標を表す構造体とクラスを用いて違いを確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
using System; public struct Point { // 読み取り専用プロパティ public int X { get; } public int Y { get; } // コンストラクタで値を設定 public Point(int x, int y) { X = x; Y = y; } } public class PointClass { public int X { get; set; } public int Y { get; set; } public PointClass(int x, int y) { X = x; Y = y; } } public class ExampleUsage { public static void Main() { // 構造体の使用例(値型) Point p1 = new Point(10, 20); Point p2 = p1; // 実体のコピーが作られる p2 = new Point(100, 20); // p2を変更してもp1は変化しない // クラスの使用例(参照型) PointClass pc1 = new PointClass(10, 20); PointClass pc2 = pc1; // 参照がコピーされる pc2.X = 100; // pc2を変更するとpc1にも反映される Console.WriteLine($"Point: X = {p1.X}, Y = {p1.Y}"); Console.WriteLine($"PointClass: X = {pc1.X}, Y = {pc1.Y}"); } } |
Point: X = 10, Y = 20
PointClass: X = 100, Y = 20
このように、構造体はコピーが独立しているため、p2を変更してもp1には影響がありません。
クラスは同じインスタンスを共有するため、pc1とpc2のどちらを変更しても反映されることがわかります。
構造体を使用する際の注意点
構造体の利用はメリットがある一方で、いくつか注意点も存在します。
- コピーコスト:大きな構造体を頻繁にコピーするとパフォーマンス低下につながる
- 不変性の推奨:変更可能なフィールドがあると意図せぬバグが起こりやすい
- ボクシング:object型に変換するとボクシングが発生し、パフォーマンスに影響
- コンストラクタの制約:C#のバージョンによってはパラメータなしコンストラクタに注意が必要
まとめ
構造体とクラスは値型と参照型という大きな違いがあります。
用途に合わせた選択で、パフォーマンスやコードの可読性を向上させることができます。
継承の必要性やメモリ管理を考慮しながら、設計段階でどちらを使うか判断しましょう。