0Pricing
C# Academy · レッスン

定数とreadonlyフィールド

constとstatic readonlyの違いを理解します。

「定数とreadonlyフィールド」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。

値を固定する2つの方法

C# には、変更されない値を表すために const と readonly があります。見た目は似ていますが、動作は大きく異なります。このレッスンでは両者を比較します。

using System;

class Config
{
    public const double Pi = 3.14159;
    public static readonly DateTime StartedAt = DateTime.Now;
}

class Program
{
    static void Main()
    {
        Console.WriteLine("Pi = " + Config.Pi);
    }
}

const: コンパイル時定数

const は宣言時にリテラル値を割り当てる必要があり、コンパイル時に値が埋め込まれます。暗黙的に static です。

using System;

class Circle
{
    public const double Pi = 3.14159;

    public static double Area(double r) => Pi * r * r;
}

class Program
{
    static void Main()
    {
        Console.WriteLine(Circle.Area(2).ToString("0.00"));
    }
}

const はリテラルでなければなりません

コンパイル時に解決されるため、const に格納できるのは、数値、文字列、ブール値、またはほかの const などの定数式だけです。

using System;

class Limits
{
    public const int MaxRetries = 3;
    public const int Timeout = MaxRetries * 1000;   // const expression OK
}

class Program
{
    static void Main()
    {
        Console.WriteLine(Limits.MaxRetries + ", " + Limits.Timeout);
    }
}

readonly: 実行時定数

readonly フィールドは、宣言時またはコンストラクター内で一度だけ設定し、その後は変更できません。値は実行時に計算できます。

using System;

class Session
{
    public readonly string Id;

    public Session(string id)
    {
        Id = id;   // allowed: inside constructor
    }
}

class Program
{
    static void Main()
    {
        var s = new Session("abc-123");
        Console.WriteLine("Session: " + s.Id);
    }
}

readonly は実行時の値を使用できます

const とは異なり、readonly フィールドには、生成された ID や現在時刻のように、プログラムの実行時になって初めて決まる値を格納できます。

using System;

class Order
{
    public readonly Guid OrderId;

    public Order()
    {
        OrderId = Guid.NewGuid();
    }
}

class Program
{
    static void Main()
    {
        var o = new Order();
        Console.WriteLine("Has id: " + (o.OrderId != Guid.Empty));
    }
}

static readonly

実行時に一度だけ計算するクラス全体の値には、static readonly を組み合わせます。値がリテラルではない場合に、const の代わりとして通常使用されます。

using System;

class AppInfo
{
    public static readonly string[] Roles = { "admin", "user", "guest" };
}

class Program
{
    static void Main()
    {
        Console.WriteLine("Roles: " + Roles());
    }

    static int Roles() => AppInfo.Roles.Length;
}

アセンブリ間で const が危険になり得る理由

const の値はコンパイル時に呼び出し側のコードへインライン化されるため、ライブラリの public な const を変更した場合は、すべての呼び出し側を再コンパイルする必要があります。static readonly ならこの問題を避けられます。

using System;

class Lib
{
    public const int Version = 2;              // inlined into callers
    public static readonly int Build = 100;     // read at runtime
}

class Program
{
    static void Main()
    {
        Console.WriteLine(Lib.Version + "." + Lib.Build);
    }
}

どちらも再代入できない

初期化後は、const フィールドも readonly フィールドも変更できません。変更しようとするとコンパイルエラーになります。

using System;

class Demo
{
    public const int A = 10;
    public readonly int B;

    public Demo() { B = 20; }
    // A = 11;  // would not compile
    // B = 21;  // would not compile outside constructor
}

class Program
{
    static void Main()
    {
        var d = new Demo();
        Console.WriteLine(Demo.A + ", " + d.B);
    }
}

使い分け

決して変わらない真のリテラル(Pi や MaxInt)には const を使用します。実行時に値を計算する場合や、インスタンスごとに異なる可能性がある場合は readonly を使用します。

using System;

class Physics
{
    public const double Gravity = 9.81;          // universal literal
    public readonly double Mass;                  // per object

    public Physics(double mass) { Mass = mass; }
    public double Weight() => Mass * Gravity;
}

class Program
{
    static void Main()
    {
        var p = new Physics(10);
        Console.WriteLine("Weight: " + p.Weight());
    }
}

readonly 参照の注意点

readonly が固定するのはフィールドであり、そのフィールドが参照するオブジェクトではありません。readonly なリスト参照には再代入できませんが、リストの内容は変更できます。

using System;
using System.Collections.Generic;

class Cart
{
    public readonly List<string> Items = new List<string>();
}

class Program
{
    static void Main()
    {
        var c = new Cart();
        c.Items.Add("Pen");   // allowed: mutating the object
        c.Items.Add("Book");
        Console.WriteLine("Items: " + c.Items.Count);
    }
}

まとめ

一般的なクラスでは、固定されたリテラルに const を使用し、生成時にインスタンスごとに確定する値に readonly を使用します。

using System;

class Account
{
    public const decimal MinBalance = 0m;
    public readonly string Owner;

    public Account(string owner)
    {
        Owner = owner;
    }
}

class Program
{
    static void Main()
    {
        var a = new Account("Rin");
        Console.WriteLine(a.Owner + " min=" + Account.MinBalance);
    }
}

理解度チェック

const と readonly の違いについて理解できているか確認しましょう。

まとめ

const はコンパイル時のリテラルで、暗黙的に static となり、呼び出し側へインライン化されます。readonly は宣言時またはコンストラクター内で一度だけ設定でき、実行時の値を使用できます。真のリテラルには const、実行時に計算する共有値には static readonly を使用します。また、readonly が固定するのは参照であり、オブジェクト自体ではないことを覚えておきましょう。

using System;

class Demo
{
    public const int Max = 100;
    public readonly int Created;
    public Demo(int c) { Created = c; }
}

class Program
{
    static void Main()
    {
        var d = new Demo(7);
        Console.WriteLine(Demo.Max + ", " + d.Created);
    }
}

よくある質問

「定数とreadonlyフィールド」レッスンは無料ですか?

はい。「定数とreadonlyフィールド」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。

「定数とreadonlyフィールド」で何を学びますか?

constとstatic readonlyの違いを理解します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C# Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「定数とreadonlyフィールド」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC# Academyレッスンでコードを書いて実行できますか?

はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 静的メソッドとフィールド
  2. ユーティリティ用の静的クラス
  3. 定数とreadonlyフィールド
  4. 静的設計とインスタンス設計
← C# Academyに戻る