プロパティの書き方色々 ーメモのようなものー

最近、C#のプロパティの書き方についていろいろと増えてきたことに気づいたため、メモもかねて書き出してみようと思います。

### オーソドックスな定義

```cs
public ValueType PropertyName
{
    get{
        ValueType result;

        // プロパティの値取得処理

        return result;
    }

    set{
        // プロパティの値設定処理
    }
}
```

一番ベースとなる書き方です。以降の書き方は、例をこの書き方に変換したものも併せて記述します。

### 自動実装プロパティ(C#3.0以降)

```cs
public ValueType PropertyName
{
    get;
    set;
}
```

この書き方をコンパイル後、解析してみると、以下のようになっています。

```cs
private Dictionary<string,Object> m_ValueList = new Dictionary<string,Obect>();

public ValuyeType PropertyName
{
    get{
        return (ValueType)m_ValueList["PropertyName"];
    }
    set{
        m_ValueList["PropertyName"] = value;
    }
}
```

このように内部で自動実装されているプロパティの値一覧をもつDictionaryが生成され、それに対してプロパティ名(上記コード上はPropertyName)をキーにして値を取得・格納しています。
ここで注意すべきなのは、初期値を入れる機構がないため、getアクセサのみの記述では使えないことです。

### 自動実装プロパティ＋初期値設定(C#6.0以降)

```cs
public ValueType PropertyName
{
    get;
    set;
}= new ValueType();
```

これは大体以下のような書き方になります。

```cs
private Dictionary<string,Object> m_ValueList = new Dictionary<string,Obect>();

public ValuyeType PropertyName
{
    get{
        return (ValueType)m_ValueList["PropertyName"];
    }
    set{
        m_ValueList["PropertyName"] = value;
    }
}

public Constructor()
{
    m_ValueList["PropertyName"] = new ValueType();

    // コンストラクタ本来の処理
}
```

初期値の設定が可能になったことで、getアクセサのみの自動実装プロパティが使えるようになりました。
また、この記述を使うことで、Singletonの実装も以下のように簡単になります。

```cs
public static SingletonClass Instance {get;}= new SingletonClass();
```

また、初期値の設定ができるようになったことで、以下のようにgetアクセサのみの自動実装プロパティにコンストラクタで値を設定できるようになりました。

```cs
public ValueType PropertyName{get;}

public Constructor()
{
    PropertyName = new ValueType();

    // ほかのコンストラクタの処理
}
```

### ラムダ式を使ったプロパティの定義(C#7.0以降)

```cs
public ValueType PropertyName
{
    get=>GetMethod();
    set=>SetMethod(value);
}

private ValueType GetMethod()
{
    ValueType result;

    // プロパティの値取得処理

    return result;
}

private void SetMethod(ValueType value)
{
    // プロパティの値設定処理
}
```

これはあまり書き直す必要がないですが、以下のようになります。

```cs
public ValueType PropertyName
{
    get{
        return GetMethod();
    }
    set{
        SetMethod(value);
    }
}

// 以降は同じため省略
```

この書き方はラムダ式演算子(`=>`)を使った処理の定義の仕方で、内容が1行のみの時はこちらのほうが見やすいです。ただ、2行以上になると、ラムダ式演算子を追加しただけでオーソドックスな書き方とほぼ同じため、ただ手間が増えるだけです。

### getアクセサのみのラムダ式を使った定義(C#6.0以降)

```cs
public ValueType PropertyName => GetMethod();

private ValueType GetMethod()
{
    ValutType result;

    // プロパティの値取得処理

    return result;
}
```

こちらは以下のように書き換えられます。

```cs
public ValueType PropertyName
{
    get{
        return GetMethod();

    ]
}

// 以下は同じため省略
```

かなりすっきりした書き方になります。
ただ、以下のように書いた場合、注意が必要です。

```cs
public ValueType PropertyName => new ValueType();
```

この書き方だと、以下ととても良く似ており、混同しやすいため、個人的にはお勧めしません。

```cs
public ValueType PropertyName = new ValueType();
```

先に書いたものは取得するたびにインスタンスが異なるのに対し、こちらは何度取得しても同じインスタンス
を取得できます。
そのため、こちらのつもりで先に書いた記述をしてしまうと、「プロパティに変更が反映されていない」といったことが起きてしまいます。そういったことを防ぐために個人的にはお勧めしないのです。

### おわりに
プロパティの書き方4種類を説明しましたが、それぞれに一長一短があります。
それぞれの特性を考えて読みやすいコードを心がけていきたいです

### 参考サイト
* 自動的に実装されるプロパティ:https://learn.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/auto-implemented-properties
* プロパティ初期化子：https://ufcpp.net/study/csharp/oo_property.html#property-initializer
* 構文：メソッドやプロパティをラムダ式で簡潔に実装するには？:https://atmarkit.itmedia.co.jp/ait/articles/1606/01/news051.html