C# の struct は、値型として扱われる軽量なデータ構造です。
クラス(class)と似ていますが、メモリ管理や用途に明確な違いがあります。
struct の基本
struct は 値型(Value Type) であり、変数に代入したりメソッドに渡したりすると コピーが作られます。
宣言例
csharp
public struct PlayerStatus
{
public int hp;
public int mp;
public PlayerStatus(int hp, int mp)
{
this.hp = hp;
this.mp = mp;
}
}
特徴まとめ
- 値型(スタックに配置されやすい)
- 継承不可(インターフェースの実装は可能)
- デフォルトコンストラクタを定義できない
- 小さくて不変なデータに向く
struct と class の違い
メモリ管理の違い
- struct:値型 → コピーされる
- class:参照型 → 参照が渡される
csharp
struct A { public int x; }
class B { public int x; }
A a1 = new A { x = 10 };
A a2 = a1; // 値がコピーされる
a2.x = 20; // a1.x は 10 のまま
B b1 = new B { x = 10 };
B b2 = b1; // 参照がコピーされる
b2.x = 20; // b1.x も 20 に変わる
⚡ IMPORTANT
struct はコピーされるため、意図せず値が変わらないことがある。
class と同じ感覚で扱うとバグの原因になる。
class と同じ感覚で扱うとバグの原因になる。
struct を使うべきケース
struct が向いている場面
小さくて不変なデータ
例:座標、色、短いステータス情報頻繁に生成される軽量データ
→ GC 負荷を減らせるUnity での軽量データ構造
Vector3やQuaternionなども struct
💡 TIP
struct は 16 バイト以下が推奨とされることが多い。
大きすぎる struct はコピーコストが高くなる。
大きすぎる struct はコピーコストが高くなる。
struct を避けるべき場面
- 大きなデータを持つ
- ミュータブル(可変)なデータ
- 継承を使いたい
- 参照共有したい
readonly struct / ref struct
readonly struct
不変データを表すための構造体。
csharp
public readonly struct Damage
{
public int Value { get; }
public Damage(int value) => Value = value;
}
ℹ️ NOTE
フィールドも自動的に readonly として扱われるため、安全性が高い。
ref struct
スタック上にしか置けない特殊な struct。Span<T> などが代表例。
⚠️ WARNING
ref struct はクラスのフィールドにできないなど制約が多い。
実用例(ゲーム・業務アプリ・Unity)
1) ゲーム開発:座標やステータスの軽量管理
csharp
public struct Position
{
public float x;
public float y;
public Position(float x, float y)
{
this.x = x;
this.y = y;
}
}
public class Enemy
{
public Position pos;
public int hp;
public void Move(float dx, float dy)
{
pos.x += dx;
pos.y += dy;
}
}
💡 TIP
座標のような「小さくて頻繁に使うデータ」は struct が最適。
2) 業務アプリ:不変データの表現(readonly struct)
csharp
public readonly struct Money
{
public decimal Amount { get; }
public string Currency { get; }
public Money(decimal amount, string currency)
{
Amount = amount;
Currency = currency;
}
}
Money price = new Money(1200m, "JPY");
⚡ IMPORTANT
金額や日付など「不変であるべきデータ」は readonly struct が安全。
3) Unity:物理計算や軽量データの受け渡し
csharp
public struct HitInfo
{
public Vector3 point;
public float damage;
public HitInfo(Vector3 point, float damage)
{
this.point = point;
this.damage = damage;
}
}
void OnHit(HitInfo hit)
{
Debug.Log($"Hit at {hit.point}, damage={hit.damage}");
}
🔴 CAUTION
struct を引数で渡すとコピーされるため、巨大な struct は避ける。
まとめ
- struct は 軽量な値型データ を表すのに最適
- コピーされる性質を理解して使うことが重要
- 不変データ・小さなデータに向く
- Unity でも頻繁に利用される
- 実用例として「座標」「金額」「ヒット情報」などが典型