こんにちは。前回は「const、readonly、static readonlyの使い方・違いについて」説明していきました。
詳しくは、こちらの記事をご覧ください。
今回は前回入りきらなかった「const」を使用する時の注意点を解説していきます。
constのバージョン管理問題
constで宣言した定数はアクセス修飾子をpublicにすべきでない。と言われています。
なぜかというと、const定数はコンパイル時点で値が決定します。
例えば、クラスライブラリのMyClassには、constの定数”MAX_COUNT”が宣言されています。
public class MyClass {
public const int MAX_COUNT = 25;
}
Program.exeに含まれるProcessクラスでは、ライブラリを読み込んでMyClass.MAX_COUNTを使います。
public class Process {
for(int i = 0; i < MyClass.MAX_COUNT; i++) {
…
}
}
仕様が変わりMAX_COUNTが30になったので、constの定数を変更しました。
public class MyClass {
public const int MAX_COUNT = 30;
}
このとき、クラスライブラリだけコンパイルして差し替えた場合、Program.exeで使用するときはMyClass.MAX_COUNTの値はどうなるでしょうか?
…正解はMyClass.MAX_COUNTの値は25になります。
理由はProgram.exeで使用しているMyClass.MAX_COUNTの値はProgram.exeをコンパイルするときに値が決まっているからです。
これをバージョンアップするときに起こる問題として、constのバージョン管理問題やconstのバージョニング問題と言います。
列挙型の代わりに構造体のconstを使わない
構造体のconstで、列挙型のような使い方をすると、予期せぬ不具合を生み出すことがあります。
こちらは構造体での使用例です。
12行目でstatusに”5″を設定していますが、何も問題なくビルドが通ります。
しかし、開発者はStatus構造体内の定数を設定したいはずなので、statusに”5″を代入してしまうことは以降の処理で不具合を起こしかねません。
struct Status
{
public const int INIT = 0;
public const int FAILED = 1;
public const int SUCCESS = 2;
public const int FINAL = 3;
}
var status = Status.INIT;
// Statusには存在しない値を設定できる
status = 5;
続いて、列挙型での使用例です。
12行目のように列挙型での宣言後、Statusに存在しない値を設定すると、ビルドエラーになります。
enum Status
{
INIT = 0;
FAILED = 1;
SUCCESS = 2;
FINAL = 3;
}
var status = Status.INIT;
// Statusに存在しない値を設定すると、ビルドエラーになる
status = 5;
まとめ
今回は前回の定数の解説に引き続き、「const」に焦点を当てて注意点を解説していきました。
特に「バージョン管理問題」は現象が起こった際にハマりやすいところだと思いますので、頭の片隅に置いておいた方が良いと思います!
良かったら他の記事もご覧になってください。