定数
定数の使い方 ▲
public const int NUM = 5;
NUM = 10; // 定数を書き換えることはできないのでエラー
const を付けて宣言された定数は、宣言文中における初期化時にのみ値を代入できる
また定数は原則として大文字で命名する
これによって第三者がすぐに定数だと判断することができ、また万が一書き換えてもエラーによって気づくことができる
また定数はリテラルと同じようにコンパイルによって値が展開されるため、処理速度も速い
定数の注意 ▲
上記で書いたとおりコンパイル時は値が展開されるため、例えばライブラリで定数を定義して、別プロジェクトのアプリから参照するような場合は注意が必要である
ライブラリ側の定数の値を書き換えてライブラリだけをコンパイルしたとしても、参照しているアプリ側ではアプリのビルド時に既に古い値で展開されている状態のため、値が反映されない状態になってしまう
このような問題をバージョンアップしたときの挙動が怪しくなるという意味で、バージョニング問題と呼ぶ
なので数学のπ(円周率)のように値が変わること自体がまずないものであれば定数でよいが、もしも変更がありうるのであれば、たとえ定数であっても static なプロパティにしておくほうが良い
readonly ▲
クラスのメンバであれば const 以外に定数のような扱いをできるキーワードとして readonly がある
const と readonly の違いは以下である
const | readonly |
---|---|
ローカル変数にも使える | クラスのメンバ変数のみ |
常に静的変数と同じ扱い | static の有無を変えられる |
宣言時にのみ初期化可能 | コンストラクタ内で値を書き換え可能 |
コンパイル結果はリテラルと同様 | コンパイル結果は変数と同様 |
インスタンスを new で生成するようなものには使えない | new 可能 |
ただし readonly の注意点として、再帰的には働かないという点がある
readonly を付けたそのメモリだけが読み取り専用になり、参照先については書き換え可能なことに注意する
例えば下記のようなケースである(参考文献2より)
// 書き換え可能なクラス
class MutableClass
{
// フィールドを直接公開
public int X;
// 書き換え可能なプロパティ
public int Y { get; set; }
// フィールドの値を書き換えるメソッド
public void M(int value) => X = value;
}
class Program
{
static readonly MutableClass c = new MutableClass();
static void Main()
{
// これは許されない。c は readonly なので、c 自体の書き換えはできない
c = new MutableClass();
// けども、c の中身までは保証してない
// 書き換え放題
c.X = 1;
c.Y = 2;
c.M(3);
}
}
目次