2014年3月8日土曜日

C#でのreadonlyの罠

C#での定数はconst定数とreadonly定数の2種類がある。
const定数では参照型を代入することができないがreadonly定数ではできる。
またconst定数はリテラルとして扱われるが、readonly定数は普通の変数として扱われる。

readonly定数は完全にconstantな訳でなく、フィールドやプロパティの
書き換えは行えてしまう。

class A
{
    public int a;
    public int b
    {
        get;
        set;
    }
}

class B
{
    public static readonly A a = new A();
    public void test()
    {
        //コンパイルエラーにならない
        a.a = 3;
        a.b = 4;
    }
}
C++は比較的まともなconstオブジェクトを作れるので、その点ではC#より優れていると言える。

またreadonly定数は普通の変数として扱われる。そのためランタイムに初期化を行うので、readonly定数の初期化に初期化されていないreadonly定数を使うとバグが発生する。
class A
{
    //Cが初期化される前にBが初期化されてしまうためにBが3になる
    public static readonly int B = C + 3;
    public static readonly int C = 4;
}

C#erには常識かもしれないがC#初心者の私は引っかかってしまった。