C#のpublic constには気を付けよう

C#で定数を定義するときconstやstatic readonlyなどを使います。

例えば以下のようにconstの定数Test1と静的変数Test2があったとします。

public class ConstSample
{
    public const int Test1 = 1;
    public static readonly int Test2 = 2;
}

ConstSample.Test1 や ConstSample.Test2 のように別のクラスから参照できます。
static readonly のほうは静的変数なので初期値は自由に設定できますが、
const のほうは定数なので、実行してから決まるような値は使えません。

switch文のcaseでは 定数である ConstSample.Test1 のほうは使えますが、
変数である ConstSample.Test2 のほうは使えません。

用途にあわせてどちらを使ってもよいかと思いますが、
const 定数では予期しない動作になる場合があります。

それは dll などのクラスでpublic const を定義し、別のアセンブリから参照するケースです。

以下のようなSampleLib.dllがあったとします。

namespace SampleLib
{
    public class ConstSample
    {
        public const int Test1 = 1;
        public static readonly int Test2 = Test1;
    }
}

これは Test1 も Test2 も 1 である想定でしょう。

これを以下のように、別アセンブリのSample.exeから参照してみます。

namespace Sample
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine($"Test1={SampleLib.ConstSample.Test1}");
            Console.WriteLine($"Test2={SampleLib.ConstSample.Test2}");
        }
    }
}

両方をビルドして実行すると
Test1=1
Test2=1
と出力されます。これは想定通りです。

では、dll側の変更が必要になり、変更後のdllと差し替えるケースを考えてみます。

namespace SampleLib
{
    public class ConstSample
    {
        public const int Test1 = 2;
        public static readonly int Test2 = Test1;
    }
}

Test1 と Test2 は 2 に変更になりました。
これをビルドして先ほどのdllと差し替えます。
そして Sample.exe を実行すると
Test1=1
Test2=2
となります。

Test1 が 2 になっていません。

constはビルド時には値が決定するので、dllを差し替えただけでは const の値は反映されません。
一方でstatic readonlyは実行時に決定するので、正しく反映されます。
constの値も正しく反映させるためには参照しているexeのほうも再ビルドする必要があります。
dllだけ変更して差し替えをするような場合ではpublic constの使用は避けたほうがよいでしょう。

スポンサーリンク