| 修飾子 | 評価タイミング | 宣言での初期化 | コンストラクタでの初期化 |
|---|---|---|---|
| const | コンパイル時 | ○ (必須) | × |
| readonly | 実行時 | ○ | ○ |
class MyClass
{
const int c1 = 0;
const int c2; // error CS0145: const フィールドに値を指定する必要があります。
readonly int r1;
readonly int r2; // warning CS0649: フィールド 'MyClass.r2' は割り当てられません。常に既定値 0 を使用します。
MyClass()
{
r1 = 0;
}
void A()
{
c1 = 1; // error CS0131: 代入式の左辺には変数、プロパティ、またはインデクサーを指定してください。
r1 = 1; // error CS0191: 読み取り専用フィールドに割り当てることはできません (コンストラクター、変数初期化子では可 )。
}
}
constはコンパイル時に評価されるため、宣言での初期化が必須です。そしてconstで定数に指定できるのは、
に限られます。const (C# リファレンス) | MSDN
class MyClass
{
const int i = 1;
const bool b = true;
const MyEnum e = MyEnum.A;
const string s = "abc";
const int[] a = null; // null参照
const MyClass c = null; // null参照
const int[] a1 = new int[3]; // error CS0133: 'MyClass.a1' に割り当てられた式は定数でなければなりません。
readonly int[] a2 = new int[3]; // ok
const MyClass c1 = new MyClass(); // error CS0133: 'MyClass.c1' に割り当てられた式は定数でなければなりません。
readonly MyClass c2 = new MyClass(); // ok
void A()
{
i = 10; // error CS0131: 代入式の左辺には変数、プロパティ、またはインデクサーを指定してください。
b = false; // error CS0131: 代入式の左辺には変数、プロパティ、またはインデクサーを指定してください。
e = MyEnum.B; // error CS0131: 代入式の左辺には変数、プロパティ、またはインデクサーを指定してください。
s = "x"; // error CS0131: 代入式の左辺には変数、プロパティ、またはインデクサーを指定してください。
}
}
readonlyは実行時に評価されるため、
readonly uint l = (uint)DateTime.Now.Ticks;
のような毎回異なる値も定数にできます。また初期化は宣言またはコンストラクタのいずれでもよく、初期化しない場合には既定値が設定されます。readonly キーワード - C# reference | Microsoft Learn
readonlyは、次のものに指定できます。
定数とは異なりますが、コレクションを読み取り専用とするならばIReadOnlyList<T>などを用いる方法もあります。
IReadOnlyList<int> col = new Collection<int>(new[] { 1, 2 });
col[0] = 3; // error CS0200: プロパティまたはインデクサー 'IReadOnlyList<int>.this[int]' は読み取り専用であるため、割り当てることはできません
静的なフィールドは、初めてアクセスされる前、もしくは静的コンストラクタがあるならばそれが呼び出される前に初期化されます。静的メンバー - 静的クラスと静的クラス メンバー - C# プログラミング ガイド | Microsoft Learn
値をコンパイル時に決定できるならば、static readonlyではなくconstとします。
CA1802: Use Literals Where Appropriate - Visual Studio 2015 | Microsoft Learn
c# - 'Static readonly' vs. 'const' - Stack Overflow
宣言時に値が確定しているならばそこで初期化して、静的コンストラクタでは初期化しないようにします。CA1810: Initialize reference type static fields inline - Visual Studio 2015 | Microsoft Learn
class MyClass
{
static int a = 1; // ここで初期化する
static int b;
// 静的コンストラクタ
static MyClass()
{
b = 1; // ここでも初期化できる
}
}
Type.GetField()で任意のフィールドの情報を取得し、アクセスできます。