なんだかGoodVibes

日々の勉強メモです。

プロパティについて調べてみました。

プロパティとは、privateなフィールドの値を
読み書きするためのメンバーです。
プロパティはget,setのブロックがついており
これらはアクセサと呼ばれる特別なメソッドです。
サンプルを書きながら説明していきます。

public class MainClass
{
    public void main()
    {
        var sample1 = new Sample1();
        sample1.Num = 10;
        Console.WriteLine($"sample1.Numの値は「{sample1.Num}」です。");

        sample1.Num = 200;
        Console.WriteLine($"sample1.Numの値は「{sample1.Num}」です。");
    }
}

public class Sample1
{
    private int num;

    public int Num
    {
        get
        {
            return num;
        }
        set
        {
            num = value;
        }
    }
}

出力は以下です。

sample1.Numの値は「10」です。
sample1.Numの値は「200」です。

サンプルのgetが値の読み取り、set部分が設定を行います。
プロパティは、呼び出し側から見るとはメンバー変数を呼び出しているように振る舞い、
クラス内部からはメソッドのように振る舞います。

次は設定できる値に制約をもたせたサンプルです。

public class MainClass
{
    public void main()
    {
        var sample2 = new Sample2();
        sample2.Num = 10;
        Console.WriteLine($"sample2.Numの値は「{sample2.Num}」です。");

        sample2.Num = 200;
        Console.WriteLine($"sample2.Numの値は「{sample2.Num}」です。");
    }
}

public class Sample2
{
    private int num;

    public int Num
    {
        get
        {
            return num;
        }
        set
        {
            // 設定できる値を10〜100とする
            if (value >= 10 && value <= 100)
            {
                num = value;
            }
            else
            {
                Console.WriteLine("10から100の間の値を設定してください。");
            }
        }
    }
}

出力は以下です。

sample2.Numの値は「10」です。
10から100の間の値を設定してください。
sample2.Numの値は「10」です。

setは値を設定を行うので、setの部分で条件式を記載しています。
サンプルの出力をみると条件に当てはまる場合は値を設定し、
そうでない場合はそれまでの値が保持されているのがわかりますね。

今までのサンプルではget,setの両方が存在しますね。
アクセサにgetしか存在しない、もしくはsetしか存在しないプロパティもあります。
getのみのプロパティを読み取り専用プロパティ、setのみのプロパティを書き込み専用プロパティといいます。

public class MainClass
{
    public void main()
    {
        var sample3 = new Sample3();
        // 値を設定しようとするとエラーとなる。
        // sample3.ReadOnlyNum = 10;
        Console.WriteLine($"sample3.Numの値は「{sample3.ReadOnlyNum}」です。");

        sample3.WriteOnlyNum = 100;
        // 値を読み取ろうとするとエラーとなる。
        // Console.WriteLine($"sample3.Numの値は「{sample3.WriteOnlyNum}」です。");
    }
}

public class Sample3
{
    private int readOnlyNum;

    private int writeOnlyNum;

    /// <summary>
    /// 読み取り専用
    /// </summary>
    public int ReadOnlyNum
    {
        get
        {
            return readOnlyNum;
        }
    }

    /// <summary>
    /// 書き込み専用
    /// </summary>
    public int WriteOnlyNum
    {
        set
        {
            writeOnlyNum = value;
        }
    }

    /// <summary>
    ///  コンストラクタ
    /// </summary>
    public Sample3()
    {
        this.readOnlyNum = 150;
    }
}

getのみの読み取り専用のプロパティの場合

// sample3.ReadOnlyNum = 10;

値を設定しようとするとエラーとなります。
出力される値は

sample3.Numの値は「150」です。

となり、コンストラクタで設定された値が出力されます。
コンストラクターで値を代入して以降は、書き換え不能になります。

setのみの書き込み専用のプロパティの場合

// Console.WriteLine($"sample3.Numの値は「{sample3.WriteOnlyNum}」です。");

値を読み取ろうとするとエラーとなります。

get,setには異なるアクセスレベルを設定できます。

public class MainClass
{
    public void main()
    {
        var sample4 = new Sample4();
        // 値を設定しようとするとエラーとなる。
        // sample4.Num = 10;
        Console.WriteLine($"sample4.Numの値は「{sample4.Num}」です。");
    }
}

public class Sample4
{
    private int num;

    public int Num
    {
        get
        {
            return num;
        }

        private set
        {
            num = value;
        }
    }

    /// <summary>
    ///  コンストラクタ
    /// </summary>
    public Sample4()
    {
        this.num = 150;
    }
}

setをprivateにしているので、値を設定しようとするとエラーになります。

// sample4.Num = 10;

出力は以下です。

sample4.Numの値は「150」です。

最後に自動プロパティのサンプルを記載します。
本記事の一番最初に記載したサンプル(Sample1)を自動プロパティで書いてみます。

public class MainClass
{
    public void main()
    {
        var sample5 = new Sample5();
        sample5.Num = 10;
        Console.WriteLine($"sample5.Numの値は「{sample5.Num}」です。");

        sample5.Num = 200;
        Console.WriteLine($"sample5.Numの値は「{sample5.Num}」です。");
    }
}

public class Sample5
{
    public int Num { get; set; }
}

出力は以下になります。

sample5.Numの値は「10」です。
sample5.Numの値は「200」です。

同じ結果になりました。
このサンプルは、本記事の一番最初に記載したサンプル(Sample1)が自動生成します。
コードもスッキリしてい見やすくなりましたね。