ITコンサルの日常

ITコンサル会社に勤務する普通のITエンジニアの日常です。

readonlyフィールド

プログラミングC# p100

最初の一回だけ代入可能なフィールドのことらしい。

using System;

class RDOnly
{
        public static readonly int a;

        static RDOnly()
        {
                a = 12;
        }

        static void Main(string[] args)
        {
                Console.WriteLine("RDOnly.a = {0}", RDOnly.a);
                RDOnly.a = 24;
        }
}

これをコンパイルするとエラー。

readonly.cs(15,3): error CS0198:
        静的読み取り専用フィールドへの割り当てはできません
        (静的コンストラクタまたは変数初期化子では可)。

書籍中ではstaticフィールドに対してreadonly付けてましたが、インスタンスフィールドに対してもreadonly付けられます。

using System;

class RDOnly
{
        public readonly int a;

        RDOnly()
        {
                a = 12;
        }

        static void Main(string[] args)
        {
                RDOnly rd = new RDOnly();
                Console.WriteLine("rd.a = {0}", rd.a);
                //rd.a = 24;
        }
}

コメントをはずすと同様のエラーが出る。


そういえばと思い出して、Javaでプログラムを書いてみたら、同じ様なことが出来た。

public class ReadOnly
{
        public final int aaa;

        public ReadOnly()
        {
                this.aaa = 12;
                this.aaa = 24; // コンパイルエラー
        }

        public static void main(String[] args)
        {
                ReadOnly ro = new ReadOnly();
                System.out.println(ro.aaa);
        }
}

Java言語規定 / クラス / 8.3.1.2 finalフィールドによると、

フィールドは,final 宣言できる。この場合,宣言子に変数初期化子を含まなければならない。そうでなければ,コンパイル時エラーが発生する。

ってなんか微妙に違うような。
宣言子に変数初期化子を含まなければならない。っていうのは、
public final int aaa = 12;
みたいなことを言うのではないのかなぁ。

コンストラクタではなく、mainの方で初期化してみる。

public class ReadOnly
{
        public final int aaa;

        public ReadOnly()
        {
                //this.aaa = 12;
        }

        public static void main(String[] args)
        {
                ReadOnly ro = new ReadOnly();
                ro.aaa = 12;
                System.out.println(ro.aaa);
        }
}

コンパイル結果はこう。

ReadOnly.java:13: final 変数 aaa に値を代入することはできません。
                ro.aaa = 12;

インスタンスフィールドは、コンストラクタで初期化しないとダメみたい。
ちなみにstaticフィールドは、static初期化子で初期化しないとダメみたい。
staticフィールドはあんまり使い道なさそうだけど、インスタンスフィールドは何かの役に立つかも。