定数と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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 静的メソッドとフィールド
- ユーティリティ用の静的クラス
- 定数とreadonlyフィールド
- 静的設計とインスタンス設計