C#_値型につける readonly

クラス ( 参照型 ) とは対照的に、
構造体 ( 値型 ) の場合はデータを直接持つ。
故に、readonly を付けると構造体の中身も読み取り専用になる。

但し、
メソッドの呼び出しなどを行う際、コピーが発生するという別の注意が必要。
メソッドを呼び出す際、常にコピーが発生している。

ex )
構造体 のインスタンスに readonly

    struct MutableClass
    {
        // フィールドを直接公開
        public int X;

        // フィールドの値を書き換えるメソッド
        public void M(int value) => X = value;
    }

    class Main
    {
        static readonly MutableClass c = new MutableClass();
       
        static void Main()
        {
            // c = new MutableClass();
            // ↑は構文エラー
           
            // c.X = 1;
            // ↑ もNG。
           
           
            c.M(3);
            // ↑は書き換えメソッドを呼べてしまう。エラーにならない。
           
            Console.WriteLine(c.X); // だが値は 0 のまま
        }
    }

c.M(3) は以下のようなことになっている。

    var local = c;
    local.M(3);

故に、
c.X は 0 のままだが、locax.X は書き変わって 3 となる。
creadonly だが、 localreadonly でない

 

C# ではこのような場合、readonly を保証しつつメソッドを呼べるように
コピーしてから、そのコピーに対してメソッドを呼ぶことをしている。

メソッド内で書き換えをしているかどうかに関わらず、常にコピーしている。

 

構造体の this 書き換え

this にした場合、Main で値書き換えメソッドを使うと
X 、Y は書き換わる。

    struct
    {
        public readonly int X;
        public readonly int Y;
       
        public Point(int x, int y) => (X, Y) = (x, y);
       
        public void Set(int x, int y)
        {
            this = new Point(x, y);    // 書き換えられてしまう。
            // X = x; Y = y; は NG。
        }
    }

なお、 C# 7.2 ( Visual Studio 2017 ) では構造体自体に
readonly を付けられるようになったもよう。
this 参照 も readonly 扱いになる。( my環境は2015 )

 

基本、static readonly が推奨らしい。

 

こちらから。
http://ufcpp.net/study/csharp/resource/readonlyness/
https://qiita.com/tanakaworld/items/eda69da263e24adfa07d

 

以上。