ホームに戻る
出典 :
関連 :
目次 :
C#におけるconstとreadonly
いずれも修飾された変数を読み取り専用(書き換え不可)とする効果を持つが、振舞は厳密には異なる。
const
値がコンパイル時に確定する定数(コンパイル時定数)を宣言する際に用いる。
即ち、コンパイル時に値が確定するプリミティブ型、または文字列型のみをconst修飾できる。
以下の特徴を有する。
- 必ず固定値が埋め込まれるため、クラスメンバに指定した場合でもインスタンスに依存せず、(すべてのインスタンスで)常に同じ値になる。
よって暗黙的にstaticとなり、インスタンス名ではなくクラス名から参照する。
- ローカル変数にも適用できる。
- 値がコードに埋め込まれるため、コンパイル後のファイルサイズは大きくなるが、実行速度は速い。
- 宣言時にのみ初期化ができる(宣言時の初期化が必須)。
- switch - caseやデフォルト引数の値として使用できる。
(デフォルト引数は、その引数に値が指定されなかった場合デフォルト値を定数(const)として埋め込む)
void Fuga(int arg = 100)
{
:
}
Fuga(); //< 引数なしの Fuga() はコンパイル時に Fuga(100) に置換される
- 値がコンパイル時に確定する都合上、アセンブリ内のconst値を変更すると、
当該アセンブリの参照元をリビルドしないと変更が反映されない(バージョニング問題)。
(「アセンブリ」とは、コンパイル済のコードライブラリ(EXE / DLL)を指す。)
- コンパイル時定数は、コンパイルの際にコードが定数に置き換わる。即ち、リテラルを直接記述した場合と同等となる。
このため、初期値には定数式以外をとることができない。
class Hoge
{
public const double PI = 3.14; //< 定数式なのでOK
public const double piyo = PI * PI; //< 定数式(定数同士の演算)なのでOK
public const double payo = Math.Sqrt(10); //< 定数式でない(メソッドの呼び出し)のでNG ⇒ コンパイルエラー
void Piyo()
{
// コンパイル時に、シンボル PI は定数 3.14 に置換される
if (Moge == PI)
{
:
}
}
}
readonly
値を実行時に取得する読み取り専用変数(実行時定数扱い)を宣言する際に用いる。
即ち実行時まで値が確定しないが、初期化後は不変となる。
- ローカル変数には適用できず、クラスのメンバ変数としてのみ使用できる。
宣言時、もしくはコンストラクタでのみ初期化が可能。
(宣言時の初期値をコンストラクタで上書きすることも可能)
- 実行時に値が決定するため常に同じ値になるとは限らず、static ではない。
(クラスメンバではなくインスタンスメンバ)。
- コンパイル時には値は確定しないため、値がコードに埋め込まれることはない(通常の変数と同様)。
- switch - caseやデフォルト引数の値としては使用できない。
- アセンブリ内のreadonly値を変更しても、当該アセンブリを差し替えれば値は更新される(参照元のリビルド不要)。
- 実行時定数はリテラルには置換されず、初期値にnewの結果や、メソッドの実行結果を使用できる。
class Hoge
{
// readonly 変数を宣言
public readonly int Piyo;
public readonly Dog taro;
Hoge (int huga)
{
// コンストラクタ内で書き換え可能
this.Piyo = huga;
this.taro = new Dog();
}
void Func(int mohu)
{
int muga = this.Piyo;
// readonly 変数を上書きすることはできない ⇒ コンパイルエラー
this.Piyo = mohu;
}
}
static readonly
定数値が必要であるが、その値の型がconst宣言で使用できない(プリミティブ型でも文字列型でもない)場合、またはその値をコンパイル時に計算できない場合に
(constの代替として)static readonly修飾を用いることで、定数値をstatic化できる。
constとは異なりバージョニング問題が発生しないため、static readonlyの使用が推奨されている。
まとめ・使い分けるポイント
- const : 将来にわたって値が変更されることが無く、かつ対象がprivate、または処理速度の低下が許容されない場合
- static readonly : 将来にわたって値が変更される可能性がある場合
- readonly : (インスタンスを跨いで)定数である必要が無い場合
|
const |
readonly |
static readonly |
値の確定時期 |
コンパイル時 |
実行時 |
実行時 |
帰属先 |
クラス (static) |
インスタンス |
クラス (static) |
適用可能な型 |
数値型、文字列 (string) |
制約なし |
制約なし |
コンストラクタでの初期化 |
不可 |
可 |
可 |
デフォルト引数、case 句への適用 |
可 |
不可 |
不可 |
バージョニング問題 |
発生する |
発生しない |
発生しない |