プロパティをSerializeFieldにしたい
Unityをやっているとこんなふうに書けたら良いのに...って思うことないですか?
[SerializeField] public string Name { get; private set; }
要は、プロパティをSerializeFieldにしてInspector上に表示したり値を保存したりしたいのです。しかし、これはうまくいきません。
なので、しかたなく以下のように書いていました。
[SerializeField] private string name; public string Name => name;
わざわざあたらしくnameというメンバ変数を書き足すのです。めんどくさいです。
しかし、これを解決する書き方を教わりました。
[field: SerializeField] public string Name { get; private set; }
SerializeFieldの前にfield:をつけるんですね。なぜこれでうまくいきのでしょう?
そもそも、なぜ
public string Name { get; private set; }
このようにかけるかというと、これはC# 3.0 で導入された自動プロパティ(auto-property, auto-implemented property)という機能によるものです。
これは、プロパティのget/setの中身の省略できるしくみですが、内部的には、
private string __name; public string Name { get { return this.__name; } set { this.__name = value; } }
というようなコードに相当するものが生成されています。 (__nameという変数にプログラマは直接アクセスできません。)
このコンパイラーによって生成されるフィールド(この例で言うと __name)は、バックフィールド(baking field: 後援フィールド)と呼ばれます。
先のコードでSerializeFieldの前に書いたfield:は、このバックフィールドを対象にしますよっという記述なのです。
なので、__nameがSerializeFieldになり、めでたくInspector上にも表示されるというわけです。
参考:
P.S
バックフィールドにSerializeField属性をつけるのは良くないという記事を見つけました。
色々理由は書かれていますが、自分としては、バッキングフィールドの命名が仕様化されていないという点が一番怖いかなと思いました。
ないとは思うけど、万一、命名規則が変わったりしたら...
qiita.com
P.S part2
もう一点使わないほうが良い理由を見つけました。バックフィールドにSerializeFieldを使っているとFormerlySerializedAsを使うのに困りますね。バックフィールドでどんな名前になっているか見えないので。