本文へスキップ
BecomeCoder

C#オブジェクト指向コース · 第2章 型を表現する · レッスン15

readonly struct / record struct とボックス化

ブラウザで完結

導入

struct(値型)をもっと安全・簡潔に書く道具がreadonly struct(中身を変更できない値型)とrecord structrecordの簡潔さ+値型)です。あわせて、値型をobjectとして扱うときに起こるボックス化という隠れたコストも知っておきましょう。

図解

flowchart TB
    S["struct(値型)"] --> RS["readonly struct<br/>不変(変更不可)で安全"]
    S --> RCS["record struct<br/>値の等価比較を自動生成"]
    V["値型 int"] -->|object に代入| BOX["ボックス化<br/>ヒープに包まれる(コスト)"]

サンプル

var t = new Temperature(25);
Console.WriteLine(t.Fahrenheit);   // 77(中身は変更できないが計算は返せる)

// record struct は値どうしの等価比較(==)が自動で入る
var p1 = new PointR(1, 2);
var p2 = new PointR(1, 2);
Console.WriteLine(p1 == p2);       // True(中身が同じなら等しい)

// ボックス化: 値型を object として扱うとヒープに包まれる(コスト)
int n = 42;
object boxed = n;                  // ボックス化(値型 → object)
int back = (int)boxed;             // アンボックス化(object → 値型)
Console.WriteLine(back);           // 42

// --- 型の定義(トップレベル文の後ろに置く)---
readonly struct Temperature
{
    public double Celsius { get; }
    public Temperature(double c) => Celsius = c;
    public double Fahrenheit => Celsius * 9 / 5 + 32;
}

record struct PointR(int X, int Y);
  • readonly struct不変な値型。生成後に中身を変えられないので安全(並行処理でも安心)
  • record structrecordの簡潔さと値型を両立し、値の等価比較(==)が自動で入る
  • ボックス化は値型をobject(やinterface)として扱うときにヒープへ包む処理。頻発するとコストになる

演習

// TODO: record struct Pair(int A, int B) を定義し、
//       new Pair(3, 4) == new Pair(3, 4) の結果を出力してください(True)
Console.WriteLine(new Pair(3, 4) == new Pair(3, 4));

___
  • 期待される出力: True
ヒント1を見る

record struct Pair(int A, int B); を末尾に1行書くだけです

ヒント2を見る

値型のrecordは中身が同じなら==Trueになります

まとめ

  • readonly structは不変な値型、record structは値型+自動の等価比較
  • 値型をobject扱いするとボックス化でヒープに包まれる(コスト)
  • 小さく不変なデータはreadonly record structが相性抜群

次回: 決まった選択肢を表すenumです。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

C# — ブラウザ内で実行

ブラウザ内でC#を動かす環境を読み込みます(初回のみ数秒)。
スクロールして表示された時点でも自動で読み込まれます。