次の方法で共有


プロパティ (F#)

プロパティ は、オブジェクトに関連付けられている値を表すメンバーです。

構文

// Property that has both get and set defined.
[ attributes ]
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName
with [ attributes-for-get ] [accessibility-modifier] get() =
    get-function-body
and [ attributes-for-set ] [accessibility-modifier] set parameter =
    set-function-body

// Alternative syntax for a property that has get and set.
[ static ] member [accessibility-modifier-for-get] [self-identifier.]PropertyName
with [ attributes-for-get ] get() =
    get-function-body
[ static ] member [accessibility-modifier-for-set] [self-identifier.]PropertyName
with [ attributes-for-set ] set parameter =
    set-function-body

// Property that has get only.
[ attributes ]
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName =
    get-function-body

// Alternative syntax for property that has get only.
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName
with [ attributes ] get() =
    get-function-body

// Property that has set only.
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName
with [ attributes ] set parameter =
    set-function-body

// Automatically implemented properties.
[ attributes ]
[ static ] member val [accessibility-modifier] PropertyName = initialization-expression [ with get, set ]

注釈

プロパティは、オブジェクト指向プログラミングにおける "has a" リレーションシップを表し、オブジェクト インスタンスに関連付けられているデータ、または静的プロパティの場合は型を表します。

プロパティの基になる値 (バッキング ストアとも呼ばれます) を明示的に指定するか、コンパイラがバッキング ストアを自動的に生成できるようにするかに応じて、2 つの方法でプロパティを宣言できます。 一般に、プロパティに単純でない実装があり、プロパティが値または変数の単純なラッパーである場合は、より明示的な方法を使用する必要があります。 プロパティを明示的に宣言するには、 member キーワードを使用します。 この宣言型構文の後には、 get メソッドと set メソッド (名前付き アクセサー) を指定する構文が続きます。 構文セクションに示されているさまざまな形式の明示的な構文は、読み取り/書き込み、読み取り専用、および書き込み専用のプロパティに使用されます。 読み取り専用プロパティの場合は、 get メソッドのみを定義します。書き込み専用プロパティの場合は、 set メソッドのみを定義します。 プロパティに get アクセサーと set アクセサーの両方がある場合、次のコードに示すように、別の構文を使用して、アクセサーごとに異なる属性とアクセシビリティ修飾子を指定できます。

// A read-only property.
member this.MyReadOnlyProperty = myInternalValue
// A write-only property.
member this.MyWriteOnlyProperty with set (value) = myInternalValue <- value
// A read-write property.
member this.MyReadWriteProperty
    with get () = myInternalValue
    and set (value) = myInternalValue <- value

getメソッドとset メソッドの両方を持つ読み取り/書き込みプロパティの場合、getsetの順序を逆にすることができます。 または、組み合わせた構文を使用する代わりに、 get のみに表示される構文と set にのみ表示される構文を指定することもできます。 これを行うと、個々の getset メソッドを簡単にコメントアウトできます(必要な場合)。 組み合わせた構文を使用する代わりに、次のコードを示します。

member this.MyReadWriteProperty with get () = myInternalValue
member this.MyReadWriteProperty with set (value) = myInternalValue <- value

プロパティのデータを保持するプライベート値は、 バッキング ストアと呼ばれます。 コンパイラでバッキング ストアを自動的に作成するには、 member valキーワードを使用し、自己識別子を省略してから、プロパティを初期化する式を指定します。 プロパティを変更可能にする場合は、 with get, setを含めます。 たとえば、次のクラス型には、自動的に実装される 2 つのプロパティが含まれています。 Property1 は読み取り専用であり、プライマリ コンストラクターに提供される引数に初期化され、 Property2 は空の文字列に初期化された設定可能なプロパティです。

type MyClass(property1 : int) =
    member val Property1 = property1
    member val Property2 = "" with get, set

自動的に実装されるプロパティは型の初期化の一部であるため、型定義のバインドやletバインドをdoする場合と同様に、他のメンバー定義の前に含める必要があります。 自動的に実装されるプロパティを初期化する式は初期化時にのみ評価され、プロパティにアクセスされるたびに評価されるわけではないことに注意してください。 この動作は、明示的に実装されたプロパティの動作とは対照的です。 これが効果的に意味するのは、これらのプロパティを初期化するコードがクラスのコンストラクターに追加されるということです。 この違いを示す次のコードを考えてみましょう。

type MyClass() =
    let random  = new System.Random()
    member val AutoProperty = random.Next() with get, set
    member this.ExplicitProperty = random.Next()

let class1 = new MyClass()

printfn $"class1.AutoProperty = %d{class1.AutoProperty}"
printfn $"class1.ExplicitProperty = %d{class1.ExplicitProperty}"

アウトプット

class1.AutoProperty = 1853799794
class1.AutoProperty = 1853799794
class1.ExplicitProperty = 978922705
class1.ExplicitProperty = 1131210765

上記のコードの出力は、 AutoProperty の値が繰り返し呼び出されたときに変更されないのに対し、 ExplicitProperty は呼び出されるたびに変更されることを示しています。 これは、明示的なプロパティの getter メソッドと同様に、自動的に実装されるプロパティの式が毎回評価されないことを示しています。

Warnung

Entity Framework (System.Data.Entity) など、自動的に実装されるプロパティの初期化にうまく機能しない基底クラス コンストラクターでカスタム操作を実行するライブラリがいくつかあります。 このような場合は、明示的なプロパティを使用してみてください。

プロパティには、クラス、構造体、判別共用体、レコード、インターフェイス、型拡張のメンバーを指定できます。また、オブジェクト式で定義することもできます。

属性はプロパティに適用できます。 プロパティに属性を適用するには、プロパティの前の別の行に属性を書き込みます。 詳細については、「属性の」を参照してください。

既定では、プロパティはパブリックです。 アクセシビリティ修飾子は、プロパティにも適用できます。 アクセシビリティ修飾子を適用するには、 get メソッドと set メソッドの両方に適用する場合は、プロパティの名前の直前に追加します。アクセサーごとに異なるアクセシビリティが必要な場合は、 get キーワードと set キーワードの前に追加します。 アクセシビリティ修飾子には、publicprivateinternalのいずれかを指定できます。 詳細については、「 アクセス制御」を参照してください。

プロパティの実装は、プロパティにアクセスするたびに実行されます。

静的プロパティとインスタンス プロパティ

プロパティには、静的プロパティまたはインスタンス プロパティを指定できます。 静的プロパティは、インスタンスなしで呼び出すことができます。また、個々のオブジェクトではなく、型に関連付けられた値に使用されます。 静的プロパティの場合は、自己識別子を省略します。 インスタンス プロパティには自己識別子が必要です。

次の静的プロパティ定義は、プロパティのバッキング ストアである静的フィールド myStaticValue があるシナリオに基づいています。

static member MyStaticProperty
    with get() = myStaticValue
    and set(value) = myStaticValue <- value

プロパティは配列に似ていますが、その場合は インデックス付きプロパティと呼ばれます。 詳細については、「 インデックス付きプロパティ」を参照してください。

プロパティの型注釈

多くの場合、コンパイラにはバッキング ストアの型からプロパティの型を推測するのに十分な情報がありますが、型注釈を追加することで型を明示的に設定できます。

// To apply a type annotation to a property that does not have an explicit
// get or set, apply the type annotation directly to the property.
member this.MyProperty1 : int = myInternalValue
// If there is a get or set, apply the type annotation to the get or set method.
member this.MyProperty2 with get() : int = myInternalValue

プロパティ セット アクセサーの使用

set演算子を使用して、<-アクセサーを提供するプロパティを設定できます。

// Assume that the constructor argument sets the initial value of the
// internal backing store.
let mutable myObject = new MyType(10)
myObject.MyProperty <- 20
printfn "%d" (myObject.MyProperty)

出力は 20 です

Abstract プロパティ

プロパティは抽象にすることができます。 メソッドと同様に、 abstract は、プロパティに関連付けられた仮想ディスパッチがあることを意味します。 抽象プロパティは、同じクラス内の定義なしで、本当に抽象にすることができます。 したがって、このようなプロパティを含むクラスは抽象クラスです。 または、抽象は単にプロパティが仮想であることを意味し、その場合は定義が同じクラスに存在する必要があります。 抽象プロパティはプライベートにすることはできません。また、1 つのアクセサーが抽象の場合は、もう一方のアクセサーも抽象である必要があります。 抽象クラスの詳細については、「 抽象クラス」を参照してください。

// Abstract property in abstract class.
// The property is an int type that has a get and
// set method
[<AbstractClass>]
type AbstractBase() =
    abstract Property1: int with get, set

// Implementation of the abstract property
type Derived1() =
    inherit AbstractBase()
    let mutable value = 10

    override this.Property1
        with get () = value
        and set (v: int) = value <- v

// A type with a "virtual" property.
type Base1() =
    let mutable value = 10
    abstract Property1: int with get, set

    default this.Property1
        with get () = value
        and set (v: int) = value <- v

// A derived type that overrides the virtual property
type Derived2() =
    inherit Base1()
    let mutable value2 = 11

    override this.Property1
        with get () = value2
        and set (v) = value2 <- v

こちらも参照ください