プロパティ (C# プログラミング ガイド)

プロパティは、プライベート フィールドの値の読み取り、書き込み、または計算を行う、柔軟な機構が用意されたメンバーです。 プロパティは、パブリック データのメンバーと同様に使用できますが、実際はアクセサーという特殊なメソッドです。 メソッドの安全性と柔軟性を高めながら、簡単にデータにアクセスできます。

プロパティの概要

  • プロパティを使えば、実装や検査コードを隠したままで、値の取得と設定についてパブリックな方法をクラスが公開できます。

  • get プロパティ アクセサーはプロパティ値を取得するために使用し、set プロパティ アクセサーは新しい値を割り当てるために使用します。 これらのアクセサーには異なるアクセス レベルを指定できます。 詳細については、「アクセサーのアクセシビリティの制限」を参照してください。

  • set アクセサーで割り当てる値は value キーワードを使用して定義します。

  • プロパティの種類には、読み取り/書き込み (get アクセサーと set アクセサーの両方を備える)、読み取り専用 (get アクセサーのみで set アクセサーはない)、書き込み専用 (set アクセサーのみで get アクセサーはない) があります。 書き込み専用のプロパティの使用頻度は低く、ほとんどの場合、機密データへのアクセスを制限するために使用されます。

  • カスタムのアクセサー コードを必要としない単純なプロパティは、式本体の定義として、または自動実装プロパティとして実装できます。

バッキング フィールドを持つプロパティ

プロパティを実装する基本的な手法の 1 つとして、プロパティ値の設定と取得にプライベート バッキング フィールドを使用する方法があります。 この方法では、get アクセサーはプライベート フィールドの値を返します。set アクセサーはプライベート フィールドに値を割り当てる前にデータ検証を実行できます。 また、どちらのアクセサーも、データの変換や計算を行ってから、データを格納したり返したりすることができます。

このパターンを説明する例を下に示します。 この例では、TimePeriod クラスは時間間隔を表しています。 クラスの内部では、seconds という名前のプライベート フィールドに時間間隔が秒単位で格納されます。 Hours という読み取り/書き込みプロパティでは、ユーザーが時間間隔を時間単位で指定できます。 get アクセサーと set アクセサーの両方で、必要に応じて時間と秒の変換が実行されます。 また、set アクセサーは、データを検証し、時間数が無効である場合に ArgumentOutOfRangeException をスローします。

using System;

class TimePeriod
{
   private double seconds;

   public double Hours
   {
       get { return seconds / 3600; }
       set { 
          if (value < 0 || value > 24)
             throw new ArgumentOutOfRangeException(
                   $"{nameof(value)} must be between 0 and 24.");

          seconds = value * 3600; 
       }
   }
}

class Program
{
   static void Main()
   {
       TimePeriod t = new TimePeriod();
       // The property assignment causes the 'set' accessor to be called.
       t.Hours = 24;

       // Retrieving the property causes the 'get' accessor to be called.
       Console.WriteLine($"Time in hours: {t.Hours}");
   }
}
// The example displays the following output:
//    Time in hours: 24

式本体の定義

プロパティ アクセサーは、通常、式の結果を割り当てるか返すだけの 1 行のステートメントで構成されます。 プロパティは、本体が式形式のメンバーとして実装できます。 式本体の定義は、=> 記号の後に、プロパティに割り当てるかプロパティから取得するための式を続けて構成します。

C# 6 以降では、読み取り専用プロパティに get アクセサーを式形式のメンバーとして実装できます。 この場合、get アクセサー キーワードと return キーワードはどちらも使用しません。 次の例では、読み取り専用 Name プロパティを式形式のメンバーとして実装しています。

using System;

public class Person
{
   private string firstName;
   private string lastName;
   
   public Person(string first, string last)
   {
      firstName = first;
      lastName = last;
   }

   public string Name => $"{firstName} {lastName}";   
}

public class Example
{
   public static void Main()
   {
      var person = new Person("Isabelle", "Butts");
      Console.WriteLine(person.Name);
   }
}
// The example displays the following output:
//      Isabelle Butts

C# 7 以降では、get アクセサーと set アクセサーのどちらも、式形式のメンバーとして実装できます。 この場合、get キーワードと set キーワードを使用する必要があります。 両方のアクセサーに式本体の定義を使用する例を次に示します。 get アクセサーで return キーワードが使用されていない点に注意してください。

using System;

public class SaleItem
{
   string name;
   decimal cost;
   
   public SaleItem(string name, decimal cost)
   {
      this.name = name;
      this.cost = cost;
   }

   public string Name 
   {
      get => name;
      set => name = value;
   }

   public decimal Price
   {
      get => cost;
      set => cost = value; 
   }
}

class Program
{
   static void Main(string[] args)
   {
      var item = new SaleItem("Shoes", 19.95m);
      Console.WriteLine($"{item.Name}: sells for {item.Price:C2}");
   }
}
// The example displays output like the following:
//       Shoes: sells for $19.95



自動実装プロパティ

ロジックを追加しなくても、プロパティの get アクセサーと set アクセサーはバッキング フィールドに値を割り当てたりバッキング フィールドから取得したりすることができます。 この自動実装プロパティを使用すると、C# コンパイラによってバッキング フィールドが透過的に提供されるため、コードを簡略化できます。

プロパティが get アクセサーと set アクセサーの両方を備えている場合は、両方を自動実装する必要があります。 自動実装プロパティを定義するには、実装を省略して get キーワードと set キーワードを使用します。 次の例は前の例と似ていますが、NamePrice が自動実装プロパティである点が異なります。 この例では、パラメーター化されたコンストラクターも削除されているため、SaleItem オブジェクトが既定のコンストラクターの呼び出しとオブジェクト初期化子を使用して初期化されています。

using System;

public class SaleItem
{
   public string Name 
   { get; set; }

   public decimal Price
   { get; set; }
}

class Program
{
   static void Main(string[] args)
   {
      var item = new SaleItem{ Name = "Shoes", Price = 19.95m };
      Console.WriteLine($"{item.Name}: sells for {item.Price:C2}");
   }
}
// The example displays output like the following:
//       Shoes: sells for $19.95



C# 言語仕様

詳細については、「C# 言語の仕様」を参照してください。 言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。

関連項目

C# プログラミング ガイド
プロパティの使用
インデクサー
et キーワード
set キーワード