📑

【C#14】fieldキーワードの使い方

に公開

概要

C#14ではfieldキーワードが追加され、自動実装プロパティにロジックを入れたい場合に必要だったprivate変数(バッキングフィールド)の宣言が不要となりました。

C#14以前のプロパティ(fieldキーワードなし)

Productクラスに2つのプロパティがある状況で、ProductIdにロジックを入れたくなった場合を考えてみましょう。

public class Product
{
    public int ProductId { get;set;  }
    public string ProductName { get; set; }
}

例えば、マイナスの値を入れるとゼロにしたい場合は、次のようにprivateな変数を宣言して実装しなければいけませんでした。

例えば次のように_productIdというprivate変数を宣言し、内部的にはこのprivate変数、バッキングフィールドと言ったりしますが、裏側で活躍するフィールドが必要でした。

    private int _productId = 123;
    public int ProductId
    {
      get => _productId;
      set
      {
        if (value < 0)
        {
          _productId = 0;
          return;
        }

        _productId = value;
      }
    }

C#14以降のfieldキーワードを使った実装

C#14で追加されたfieldキーワードを使えば次のように記述することができます。

    public int ProductId
    {
      get => field;
      set
      {
        if (value < 0)
        {
          field = 0;
          return;
        }

        field = value;
      }
    }

_productIdになっていたところは、fieldというキーワードに代わっています。_productIdのようなバッキングフィールドはC#ではお決まりの作法でしたが、その宣言をC#が内部で管理してくれるようになり、fieldというキーワードで書けるようになりました。これでも同じ動きをするようになります。

初期値の書き方

初期値はこのようにプロパティの最後に「= 123」のように記述すればOKです。

    public int ProductId
    {
      get => field;
      set
      {
        if (value < 0)
        {
          field = 0;
          return;
        }

        field = value;
      }
    } = 123;

注意点

注意点としては、fieldにはプロパティのgetとsetでしかアクセスできません。コンストラクタや、メソッドなどからアクセスしたい場合は、プロパティ名でアクセスしてください。例えばProductIdとProductNameを加工した文字列を返却するメソッドの場合はこんな感じです。

    public string GetString()
    {
      return ProductId + ":" + ProductName;
    }

内部的にもカプセル化

これまではクラス内ではバッキングフィールドとプロパティ名のどちらにもアクセスできていましたが、fieldをつかうことによりプロパティ名でのアクセスが強制され、クラス内でもカプセル化できるようになりました。
つまり、プロパティ名経由でしかアクセスできないため、素の_productIdに直接アクセスしてマイナス値を入れてしまう問題が解決されます。これにより、マイナス値が入らないプロパティとして保証されるようになったということです。
例えば_productIdを使っていれば、次のように、クラスの内部からマイナス値を入れる可能性は残されていました。

    public string GetString()
    {
      _productId = -123;  //極端に言うとこういうこと
      return ProductId + ":" + ProductName;
    }

fieldキーワードを使えば、クラスの内部からもマイナス値は入れることはできなくなっているので、内部的にもカプセル化されているといえます。

まとめ

fieldキーワードを使えば、これまでお作法的に必要だったバッキングフィールドを省略することができ、かつ、内部的にもカプセル化されることから、C#14以降は、自動実装プロパティにロジックを入れたい場合はfieldキーワードを積極的に使っていくとよいと思います。

Discussion