C#
アイキャッチ 猫

こんにちは。前回は「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」に焦点を当てて注意点を解説していきました。

特に「バージョン管理問題」は現象が起こった際にハマりやすいところだと思いますので、頭の片隅に置いておいた方が良いと思います!

良かったら他の記事もご覧になってください。