プロパティの使用 (C# プログラミング ガイド)Using Properties (C# Programming Guide)

プロパティは、フィールドとメソッドの両方の側面を結合します。Properties combine aspects of both fields and methods. オブジェクトのユーザーにとってプロパティは、プロパティへのアクセスに同じ構文を必要とするフィールドのように見えます。To the user of an object, a property appears to be a field, accessing the property requires the same syntax. クラスの実装者にとってプロパティは、get アクセサーと set アクセサーの両方またはいずれかを表す 1 つまたは 2 つのコード ブロックです。To the implementer of a class, a property is one or two code blocks, representing a get accessor and/or a set accessor. get アクセサーのコード ブロックはプロパティが読み取られる時に実行され、set アクセサーのコード ブロックはプロパティに新しい値が割り当てられるときに実行されます。The code block for the get accessor is executed when the property is read; the code block for the set accessor is executed when the property is assigned a new value. set アクセサーのないプロパティは読み取り専用と見なされます。A property without a set accessor is considered read-only. get アクセサーのないプロパティは書き込み専用と見なされます。A property without a get accessor is considered write-only. 両方のアクセサーを持つプロパティは、読み取り/書き込みです。A property that has both accessors is read-write.

フィールドとは異なり、プロパティは変数には分類されません。Unlike fields, properties are not classified as variables. そのため、プロパティを ref または out パラメーターとして渡すことはできません。Therefore, you cannot pass a property as a ref or out parameter.

プロパティには次のようなさまざまな用途があります。変更を許可する前にデータを検証したり、データをそのデータが実際に他のソース (データベースなど) から取得されるクラスで透過的に公開したり、イベントの発生や他のフィールドの値を変更するなど、データが変更されたときに、アクションを実行したりすることができます。Properties have many uses: they can validate data before allowing a change; they can transparently expose data on a class where that data is actually retrieved from some other source, such as a database; they can take an action when data is changed, such as raising an event, or changing the value of other fields.

プロパティはクラス ブロックで宣言できます。フィールドのアクセス レベル、プロパティの型、プロパティの名前、get アクセサーと set アクセサーの両方またはいずれかを宣言するコード ブロックの順で指定します。Properties are declared in the class block by specifying the access level of the field, followed by the type of the property, followed by the name of the property, and followed by a code block that declares a get-accessor and/or a set accessor. 例:For example:

public class Date
{
    private int month = 7;  // Backing store

    public int Month
    {
        get
        {
            return month;
        }
        set
        {
            if ((value > 0) && (value < 13))
            {
                month = value;
            }
        }
    }
}

この例では、set アクセサーが Month が 1 から 12 までの値に設定されていることを確認できるように、Month がプロパティとして宣言されています。In this example, Month is declared as a property so that the set accessor can make sure that the Month value is set between 1 and 12. Month プロパティは、プライベート フィールドを使用して実際の値を追跡します。The Month property uses a private field to track the actual value. プロパティのデータの実際の場所は、プロパティの "バッキング ストア" と呼ばれることがよくあります。The real location of a property's data is often referred to as the property's "backing store." プロパティがプライベート フィールドをバッキング ストアとして使用するのは一般的なことです。It is common for properties to use private fields as a backing store. フィールドは、プロパティを呼び出すことでのみ変更できるようにするため、プライベートとマークされます。The field is marked private in order to make sure that it can only be changed by calling the property. パブリックおよびプライベートのアクセス制限の詳細については、「アクセス修飾子」を参照してください。For more information about public and private access restrictions, see Access Modifiers.

自動実装プロパティは、単純なプロパティ宣言の簡単な構文を提供します。Auto-implemented properties provide simplified syntax for simple property declarations. 詳細については、「自動実装プロパティ」を参照してください。For more information, see Auto-Implemented Properties.

get アクセサーThe get Accessor

get アクセサーの本体は、メソッドの本体と似ています。The body of the get accessor resembles that of a method. プロパティの型の値を返す必要があります。It must return a value of the property type. get アクセサーの実行は、フィールドの値を読み取ることに相当します。The execution of the get accessor is equivalent to reading the value of the field. たとえば、get アクセサーからプライベート変数を返し、最適化が有効になっている場合、get アクセサー メソッドへの呼び出しはコンパイラによってインライン化されるため、メソッド呼び出しのオーバーヘッドはありません。For example, when you are returning the private variable from the get accessor and optimizations are enabled, the call to the get accessor method is inlined by the compiler so there is no method-call overhead. ただし、仮想 get アクセサー メソッドはインライン化できません。これは、コンパイラがコンパイル時にどのメソッドが実際に実行時に呼び出されるかを認識しないからです。However, a virtual get accessor method cannot be inlined because the compiler does not know at compile-time which method may actually be called at run time. 次に、プライベート フィールド name の値を返す get アクセサーを示します。The following is a get accessor that returns the value of a private field name:

class Person
{
    private string name;  // the name field
    public string Name    // the Name property
    {
        get
        {
            return name;
        }
    }
}

プロパティを参照するとき、割り当ての対象を除き、get アクセサーがプロパティの値を読み取るために呼び出されます。When you reference the property, except as the target of an assignment, the get accessor is invoked to read the value of the property. 例:For example:

Person person = new Person();
//...

System.Console.Write(person.Name);  // the get accessor is invoked here

get アクセサーは return または throw ステートメントで終わる必要があります。コントロールはアクセサー本体をフロー オフすることはできません。The get accessor must end in a return or throw statement, and control cannot flow off the accessor body.

get アクセサーを使用してオブジェクトの状態を変更するのは、悪いプログラミング スタイルです。It is a bad programming style to change the state of the object by using the get accessor. たとえば、次のアクセサーでは、number フィールドにアクセスされるたびにオブジェクトの状態が変更される副作用が発生します。For example, the following accessor produces the side effect of changing the state of the object every time that the number field is accessed.

private int number;
public int Number
{
    get
    {
        return number++;   // Don't do this
    }
}

get アクセサーは、フィールド値を返すまたは計算してから返すために使用できます。The get accessor can be used to return the field value or to compute it and return it. 例:For example:

class Employee
{
    private string name;
    public string Name
    {
        get
        {
            return name != null ? name : "NA";
        }
    }
}

前のコード セグメントで Name プロパティに値を割り当てない場合、値 NA が返されます。In the previous code segment, if you do not assign a value to the Name property, it will return the value NA.

set アクセサーThe set Accessor

set アクセサーは、戻り値の型が void のメソッドと似ています。The set accessor resembles a method whose return type is void. 型がプロパティの型の value と呼ばれる暗黙のパラメーターを使用します。It uses an implicit parameter called value, whose type is the type of the property. 次の例では、set アクセサーが Name プロパティに追加されます。In the following example, a set accessor is added to the Name property:

class Person
{
    private string name;  // the name field
    public string Name    // the Name property
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
        }
    }
}

プロパティに値を割り当てるときに、新しい値を提供する引数を使用して set アクセサーが呼び出されます。When you assign a value to the property, the set accessor is invoked by using an argument that provides the new value. 例:For example:

Person person = new Person();
person.Name = "Joe";  // the set accessor is invoked here                

System.Console.Write(person.Name);  // the get accessor is invoked here

set アクセサーでローカル変数の宣言に暗黙のパラメーター名 value を使用すると、エラーになります。It is an error to use the implicit parameter name, value, for a local variable declaration in a set accessor.

コメントRemarks

プロパティは publicprivateprotectedinternalprotected internalprivate protected のいずれかでマークできます。Properties can be marked as public, private, protected, internal, protected internal or private protected. これらのアクセス修飾子により、クラスのユーザーがプロパティにアクセスできる方法が定義されます。These access modifiers define how users of the class can access the property. 同じプロパティの getset アクセサーは、異なるアクセス修飾子を持つことができます。The get and set accessors for the same property may have different access modifiers. たとえば、getpublic にして、型の外部からの読み取り専用アクセスを許可して、setprivate または protected にすることができます。For example, the get may be public to allow read-only access from outside the type, and the set may be private or protected. 詳細については、「アクセス修飾子」を参照してください。For more information, see Access Modifiers.

static キーワードを使用して、プロパティを静的プロパティとして宣言できます。A property may be declared as a static property by using the static keyword. その場合、クラスのインスタンスが存在しなくても、呼び出し元がいつでもプロパティを使用できるようになります。This makes the property available to callers at any time, even if no instance of the class exists. 詳細については、「静的クラスと静的クラス メンバー」を参照してください。For more information, see Static Classes and Static Class Members.

プロパティは、virtual キーワードを使用して仮想プロパティとしてマークできます。A property may be marked as a virtual property by using the virtual keyword. その場合、派生クラスでは、override キーワードを使用してプロパティの動作をオーバーライドできます。This enables derived classes to override the property behavior by using the override keyword. これらのオプションの詳細については、「継承」を参照してください。For more information about these options, see Inheritance.

仮想プロパティをオーバーライドするプロパティは、sealed にすることもできます。その場合、派生クラスでは、プロパティが仮想でなくなります。A property overriding a virtual property can also be sealed, specifying that for derived classes it is no longer virtual. 最後に、プロパティは抽象として宣言できます。Lastly, a property can be declared abstract. つまり、クラスに実装はなく、派生クラスが独自の実装を記述する必要があります。This means that there is no implementation in the class, and derived classes must write their own implementation. これらのオプションの詳細については、「抽象クラスとシール クラス、およびクラス メンバー」を参照してください。For more information about these options, see Abstract and Sealed Classes and Class Members.

注意

静的プロパティのアクセサーでvirtualabstract、または override 修飾子を使用すると、エラーになります。It is an error to use a virtual, abstract, or override modifier on an accessor of a static property.

Example

この例では、インスタンス、静的、および読み取り専用のプロパティを示します。This example demonstrates instance, static, and read-only properties. キーボードから従業員の名前を受け取り、NumberOfEmployees を 1 だけインクリメントし、従業員の名前と番号を表示します。It accepts the name of the employee from the keyboard, increments NumberOfEmployees by 1, and displays the Employee name and number.

public class Employee
{
    public static int NumberOfEmployees;
    private static int counter;
    private string name;

    // A read-write instance property:
    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    // A read-only static property:
    public static int Counter
    {
        get { return counter; }
    }

    // A Constructor:
    public Employee()
    {
        // Calculate the employee's number:
        counter = ++counter + NumberOfEmployees;
    }
}

class TestEmployee
{
    static void Main()
    {
        Employee.NumberOfEmployees = 107;
        Employee e1 = new Employee();
        e1.Name = "Claude Vige";

        System.Console.WriteLine("Employee number: {0}", Employee.Counter);
        System.Console.WriteLine("Employee name: {0}", e1.Name);
    }
}
/* Output:
    Employee number: 108
    Employee name: Claude Vige
*/

Example

この例では、派生クラスで同じ名前を持つ別のプロパティによって非表示にされている基底クラスのプロパティにアクセスする方法を示します。This example demonstrates how to access a property in a base class that is hidden by another property that has the same name in a derived class.

public class Employee
{
    private string name;
    public string Name
    {
        get { return name; }
        set { name = value; }
    }
}

public class Manager : Employee
{
    private string name;

    // Notice the use of the new modifier:
    public new string Name
    {
        get { return name; }
        set { name = value + ", Manager"; }
    }
}

class TestHiding
{
    static void Main()
    {
        Manager m1 = new Manager();

        // Derived class property.
        m1.Name = "John";

        // Base class property.
        ((Employee)m1).Name = "Mary";

        System.Console.WriteLine("Name in the derived class is: {0}", m1.Name);
        System.Console.WriteLine("Name in the base class is: {0}", ((Employee)m1).Name);
    }
}
/* Output:
    Name in the derived class is: John, Manager
    Name in the base class is: Mary
*/

前の例で重要な点を次に示します。The following are important points in the previous example:

  • 派生クラスのプロパティ Name により基底クラス内のプロパティ Name が非表示になっています。The property Name in the derived class hides the property Name in the base class. このような場合、new 修飾子は派生クラスのプロパティの宣言で使用されます。In such a case, the new modifier is used in the declaration of the property in the derived class:

    public new string Name
    
  • キャスト (Employee) は基底クラスで非表示のプロパティにアクセスするために使用されます。The cast (Employee) is used to access the hidden property in the base class:

    ((Employee)m1).Name = "Mary";
    

    メンバーを非表示にする詳細については、「new 修飾子」を参照してください。For more information about hiding members, see the new Modifier.

Example

この例では、CubeSquare の 2 つのクラスが抽象クラス Shape を実装し、その抽象 Area プロパティを上書きします。In this example, two classes, Cube and Square, implement an abstract class, Shape, and override its abstract Area property. プロパティでの override 修飾子の使用に注意してください。Note the use of the override modifier on the properties. プログラムは、入力として辺を受け入れ、四角形と立方体の面積を計算します。The program accepts the side as an input and calculates the areas for the square and cube. プログラムはまた、入力として面積を受け入れ、四角形と立方体の対応する辺を計算します。It also accepts the area as an input and calculates the corresponding side for the square and cube.

abstract class Shape
{
    public abstract double Area
    {
        get;
        set;
    }
}

class Square : Shape
{
    public double side;

    public Square(double s)  //constructor
    {
        side = s;
    }

    public override double Area
    {
        get
        {
            return side * side;
        }
        set
        {
            side = System.Math.Sqrt(value);
        }
    }
}

class Cube : Shape
{
    public double side;

    public Cube(double s)
    {
        side = s;
    }

    public override double Area
    {
        get
        {
            return 6 * side * side;
        }
        set
        {
            side = System.Math.Sqrt(value / 6);
        }
    }
}

class TestShapes
{
    static void Main()
    {
        // Input the side:
        System.Console.Write("Enter the side: ");
        double side = double.Parse(System.Console.ReadLine());

        // Compute the areas:
        Square s = new Square(side);
        Cube c = new Cube(side);

        // Display the results:
        System.Console.WriteLine("Area of the square = {0:F2}", s.Area);
        System.Console.WriteLine("Area of the cube = {0:F2}", c.Area);
        System.Console.WriteLine();

        // Input the area:
        System.Console.Write("Enter the area: ");
        double area = double.Parse(System.Console.ReadLine());

        // Compute the sides:
        s.Area = area;
        c.Area = area;

        // Display the results:
        System.Console.WriteLine("Side of the square = {0:F2}", s.side);
        System.Console.WriteLine("Side of the cube = {0:F2}", c.side);
    }
}
/* Example Output:
    Enter the side: 4
    Area of the square = 16.00
    Area of the cube = 96.00

    Enter the area: 24
    Side of the square = 4.90
    Side of the cube = 2.00
*/

参照See Also

C# プログラミング ガイドC# Programming Guide
プロパティProperties
インターフェイスのプロパティInterface Properties
自動実装プロパティAuto-Implemented Properties