明示的なフィールド: Val キーワードExplicit Fields: The val Keyword

val キーワードを使用すると、クラス型または構造体型の値を格納する場所を初期化せずに宣言することができます。The val keyword is used to declare a location to store a value in a class or structure type, without initializing it. この方法で宣言されたストレージの場所は、明示的なフィールドと呼ばれます。Storage locations declared in this manner are called explicit fields. val キーワードの別の用途として、member キーワードと組み合わせて自動実装プロパティを宣言する方法があります。Another use of the val keyword is in conjunction with the member keyword to declare an auto-implemented property. 自動実装プロパティの詳細については、「プロパティ」を参照してください。For more information on auto-implemented properties, see Properties.

構文Syntax

val [ mutable ] [ access-modifier ] field-name : type-name

コメントRemarks

クラス型または構造体型のフィールドを定義するには、通常、let バインドを使用します。The usual way to define fields in a class or structure type is to use a let binding. ただし、let バインドは、クラス コンストラクターの一部として初期化する必要があります。これは、必ずしも可能または必要であるとは限らず、望ましくない場合もあります。However, let bindings must be initialized as part of the class constructor, which is not always possible, necessary, or desirable. 初期化されていないフィールドが必要な場合は、val キーワードを使用できます。You can use the val keyword when you want a field that is uninitialized.

明示的なフィールドは静的にも非静的にもできます。Explicit fields can be static or non-static. アクセス修飾子できるpublicprivate、またはinternalします。The access-modifier can be public, private, or internal. 既定では、明示的なフィールドは public です。By default, explicit fields are public. 常に private であるクラスの let バインドとは、この点が異なります。This differs from let bindings in classes, which are always private.

Primary コンストラクターを持つクラス型の明示的なフィールドには、 DefaultValue属性が必要です。The DefaultValue attribute is required on explicit fields in class types that have a primary constructor. この属性は、フィールドが 0 に初期化されることを示します。This attribute specifies that the field is initialized to zero. フィールドの型ではゼロ初期化をサポートしている必要があります。The type of the field must support zero-initialization. 型が次のいずれかである場合は、ゼロ初期化がサポートされています。A type supports zero-initialization if it is one of the following:

  • 値が 0 のプリミティブ型。A primitive type that has a zero value.
  • 標準値、外れ値、または値の表現として null 値をサポートする型。A type that supports a null value, either as a normal value, as an abnormal value, or as a representation of a value. これには、クラス、タプル、レコード、関数、インターフェイス、.NET 参照型、unit 型、判別された共用体型が含まれます。This includes classes, tuples, records, functions, interfaces, .NET reference types, the unit type, and discriminated union types.
  • .NET 値型。A .NET value type.
  • すべてのフィールドで既定値 0 がサポートされている構造体。A structure whose fields all support a default zero value.

たとえば、someField と呼ばれる変更できないフィールドには、.NET によるコンパイル済み表現を使用した、someField@ という名前のバッキング フィールドが含まれており、ユーザーは someField という名前のプロパティを使用して、格納されている値にアクセスします。For example, an immutable field called someField has a backing field in the .NET compiled representation with the name someField@, and you access the stored value using a property named someField.

変更可能なフィールドの場合、.NET によるコンパイル済み表現は .NET フィールドになります。For a mutable field, the .NET compiled representation is a .NET field.

警告

.NET Framework 名前空間System.ComponentModelには、同じ名前を持つ属性が含まれています。The .NET Framework namespace System.ComponentModel contains an attribute that has the same name. この属性の詳細については、「DefaultValueAttribute」を参照してください。For information about this attribute, see DefaultValueAttribute.

次のコードは、明示的なフィールドの使用方法を示しています。また、比較のために、プライマリ コンストラクターを持つクラスの let バインディングも示しています。The following code shows the use of explicit fields and, for comparison, a let binding in a class that has a primary constructor. let バインディングのフィールド myInt1 が private であることに注意してください。Note that the let-bound field myInt1 is private. let バインディングのフィールド myInt1 をメンバー メソッドから参照する際は、自己識別子 this は必要ありません。When the let-bound field myInt1 is referenced from a member method, the self identifier this is not required. ただし、明示的なフィールド myInt2myString を参照する際は、自己識別子が必要です。But when you are referencing the explicit fields myInt2 and myString, the self identifier is required.

type MyType() =
    let mutable myInt1 = 10
    [<DefaultValue>] val mutable myInt2 : int
    [<DefaultValue>] val mutable myString : string
    member this.SetValsAndPrint( i: int, str: string) =
       myInt1 <- i
       this.myInt2 <- i + 1
       this.myString <- str
       printfn "%d %d %s" myInt1 (this.myInt2) (this.myString)

let myObject = new MyType()
myObject.SetValsAndPrint(11, "abc")
// The following line is not allowed because let bindings are private.
// myObject.myInt1 <- 20
myObject.myInt2 <- 30
myObject.myString <- "def"

printfn "%d %s" (myObject.myInt2) (myObject.myString)

出力は次のとおりです。The output is as follows:

11 12 abc
30 def

次のコードは、プライマリ コンストラクターを持たないクラスでの明示的なフィールドの使用方法を示しています。The following code shows the use of explicit fields in a class that does not have a primary constructor. この場合、DefaultValue 属性は必要ありませんが、その型用に定義されているコンストラクターですべてのフィールドが初期化される必要があります。In this case, the DefaultValue attribute is not required, but all the fields must be initialized in the constructors that are defined for the type.

type MyClass =
    val a : int
    val b : int
    // The following version of the constructor is an error
    // because b is not initialized.
    // new (a0, b0) = { a = a0; }
    // The following version is acceptable because all fields are initialized.
    new(a0, b0) = { a = a0; b = b0; }

let myClassObj = new MyClass(35, 22)
printfn "%d %d" (myClassObj.a) (myClassObj.b)

出力は 35 22になります。The output is 35 22.

次のコードは、構造体での明示的なフィールドの使用方法を示しています。The following code shows the use of explicit fields in a structure. 構造体は値型であるため、フィールドの値を0に設定するパラメーターなしのコンストラクターが自動的に設定されます。Because a structure is a value type, it automatically has a parameterless constructor that sets the values of its fields to zero. そのため、DefaultValue 属性は必要ありません。Therefore, the DefaultValue attribute is not required.

type MyStruct =
    struct
        val mutable myInt : int
        val mutable myString : string
    end

let mutable myStructObj = new MyStruct()
myStructObj.myInt <- 11
myStructObj.myString <- "xyz"

printfn "%d %s" (myStructObj.myInt) (myStructObj.myString)

出力は 11 xyzになります。The output is 11 xyz.

キーワードを使用しないmutableフィールドでmutable構造体を初期化する場合、割り当ては、割り当ての直後に破棄される構造体のコピーで機能します。Beware, if you are going to initialize your structure with mutable fields without mutable keyword, your assignments will work on a copy of the structure which will be discarded right after assignment. そのため、構造は変更されません。Therefore your structure won't change.

[<Struct>]
type Foo =
    val mutable bar: string
    member self.ChangeBar bar = self.bar <- bar
    new (bar) = {bar = bar}

let foo = Foo "1"
foo.ChangeBar "2" //make implicit copy of Foo, changes the copy, discards the copy, foo remains unchanged
printfn "%s" foo.bar //prints 1

let mutable foo' = Foo "1"
foo'.ChangeBar "2" //changes foo'
printfn "%s" foo'.bar //prints 2

明示的なフィールドは日常的に使用するためのものではありません。Explicit fields are not intended for routine use. 通常、可能な場合は、明示的なフィールドでなく、クラスで let バインドを使用してくださいIn general, when possible you should use a let binding in a class instead of an explicit field. 明示的なフィールドは、特定の相互運用のシナリオ (ネイティブ API に対するプラットフォーム呼び出しで使用される構造体を定義する必要がある場合など) や COM 相互運用のシナリオで役立ちます。Explicit fields are useful in certain interoperability scenarios, such as when you need to define a structure that will be used in a platform invoke call to a native API, or in COM interop scenarios. 詳細については、次を参照してください。外部関数します。For more information, see External Functions. また、プライマリ コンストラクターを持たないクラスを生成する F# コード ジェネレーターを使用している場合にも、明示的なフィールドが必要になることがあります。Another situation in which an explicit field might be necessary is when you are working with an F# code generator which emits classes without a primary constructor. 明示的なフィールドは、thread-static 変数や同様のコンストラクターでも役立ちます。Explicit fields are also useful for thread-static variables or similar constructs. 詳細については、「 System.ThreadStaticAttribute 」を参照してください。For more information, see System.ThreadStaticAttribute.

キーワード member val が型定義にまとめて表示された場合は、自動的に実装されたプロパティの定義です。When the keywords member val appear together in a type definition, it is a definition of an automatically implemented property. 詳細については、「 プロパティで定義されているインターフェイスのプライベート C++ 固有の実装です。For more information, see Properties.

関連項目See also