構造体Structures

構造体は、データ量が少なく単純な動作を持つ型のクラスよりも効率的なコンパクト オブジェクト型です。A structure is a compact object type that can be more efficient than a class for types that have a small amount of data and simple behavior.

構文Syntax

[ attributes ]
type [accessibility-modifier] type-name =
    struct
        type-definition-elements-and-members
    end
// or
[ attributes ]
[<StructAttribute>]
type [accessibility-modifier] type-name =
    type-definition-elements-and-members

解説Remarks

構造体は値型です。Structures are value types, which means that they are stored directly on the stack or, when they are used as fields or array elements, inline in the parent type. クラスやレコードとは異なり、構造体のセマンティクスは値渡しです。Unlike classes and records, structures have pass-by-value semantics. これは、主にアクセスおよびコピーが頻繁に行われるデータの小規模な集約に有用であることを意味します。This means that they are useful primarily for small aggregates of data that are accessed and copied frequently.

上記の構文では、2 つの形式が示されています。In the previous syntax, two forms are shown. 1 番目のものは軽量構文ではないものの、頻繁に使用されます。これは、struct キーワードと end キーワードを使用する場合に、2 番目のものに出現する StructAttribute 属性を省略できるためです。The first is not the lightweight syntax, but it is nevertheless frequently used because, when you use the struct and end keywords, you can omit the StructAttribute attribute, which appears in the second form. StructAttribute は省略して単に Struct とすることができます。You can abbreviate StructAttribute to just Struct.

の構文の型定義要素とメンバーは、メンバーの宣言と定義を表します。The type-definition-elements-and-members in the previous syntax represents member declarations and definitions. 構造体にはコンス トラクター、可変フィールド、および不変フィールドを含めることができ、メンバーとインターフェイス実装を宣言できます。Structures can have constructors and mutable and immutable fields, and they can declare members and interface implementations. 詳細については、「メンバー」を参照してください。For more information, see Members.

構造体は、継承に参加することも、let または do バインディングを含めることも、それ自身の型のフィールドを再帰的に含めることもできません (ただし、それ自身の型を参照する参照セルを含めることができます)。Structures cannot participate in inheritance, cannot contain let or do bindings, and cannot recursively contain fields of their own type (although they can contain reference cells that reference their own type).

構造体では let バインディングは使用できないため、val キーワードを使用して構造体のフィールドを宣言する必要があります。Because structures do not allow let bindings, you must declare fields in structures by using the val keyword. val キーワードではフィールドとその型が定義されますが、初期化は実行できません。The val keyword defines a field and its type but does not allow initialization. 代わりに、val 宣言がゼロまたは null に初期化されます。Instead, val declarations are initialized to zero or null. このため、暗黙のコンストラクター (宣言で構造体名の直後に指定されるパラメーター) を含む構造体では、val 宣言に DefaultValue 属性で注釈を付ける必要があります。For this reason, structures that have an implicit constructor (that is, parameters that are given immediately after the structure name in the declaration) require that val declarations be annotated with the DefaultValue attribute. 定義されたコンストラクターを含む構造体でも、ゼロ初期化がサポートされます。Structures that have a defined constructor still support zero-initialization. したがって、DefaultValue 属性は、このようなゼロ値がフィールドに対して有効であることの宣言になります。Therefore, the DefaultValue attribute is a declaration that such a zero value is valid for the field. 構造体の暗黙的なコンストラクターでは動作は実行されません。これは、let バインディングと do バインディングがその型では許可されていないためですが、渡された暗黙のコンストラクターのパラメーター値はプライベート フィールドとして使用できます。Implicit constructors for structures do not perform any actions because let and do bindings aren’t allowed on the type, but the implicit constructor parameter values passed in are available as private fields.

明示的なコンストラクターにフィールド値の初期化が含まれる場合があります。Explicit constructors might involve initialization of field values. 明示的なコンストラクターを含む構造体がある場合も、ゼロ初期化がサポートされます。ただし、明示的なコンストラクターと競合するため、DefaultValue 宣言では val 属性を使用しません。When you have a structure that has an explicit constructor, it still supports zero-initialization; however, you do not use the DefaultValue attribute on the val declarations because it conflicts with the explicit constructor. 宣言の詳細valについては、「明示的なフィールド:valキーワード」を参照してください。For more information about val declarations, see Explicit Fields: The val Keyword.

構造体では属性およびアクセシビリティ修飾子が許可されており、その他の型と同じ規則に従います。Attributes and accessibility modifiers are allowed on structures, and follow the same rules as those for other types. 詳細については、「属性アクセス制御」を参照してください。For more information, see Attributes and Access Control.

次のコード例は構造体の定義を示しています。The following code examples illustrate structure definitions.

// In Point3D, three immutable values are defined.
// x, y, and z will be initialized to 0.0.
type Point3D =
    struct
        val x: float
        val y: float
        val z: float
    end

// In Point2D, two immutable values are defined.
// It also has a member which computes a distance between itself and another Point2D.
// Point2D has an explicit constructor.
// You can create zero-initialized instances of Point2D, or you can
// pass in arguments to initialize the values.
type Point2D =
    struct
        val X: float
        val Y: float
        new(x: float, y: float) = { X = x; Y = y }

        member this.GetDistanceFrom(p: Point2D) =
            let dX = (p.X - this.X) ** 2.0
            let dY = (p.Y - this.Y) ** 2.0
            
            dX + dY
            |> sqrt
    end

構造体ByRefLike structs

like セマンティクスにbyref準拠できる独自の構造体を定義できます。 ByrefsYou can define your own structs that can adhere to byref-like semantics: see Byrefs for more information. これはIsByRefLikeAttribute属性で行われます。This is done with the IsByRefLikeAttribute attribute:

open System
open System.Runtime.CompilerServices

[<IsByRefLike; Struct>]
type S(count1: Span<int>, count2: Span<int>) =
    member x.Count1 = count1
    member x.Count2 = count2

IsByRefLikeは をStruct意味しません。IsByRefLike does not imply Struct. 両方とも型に存在する必要があります。Both must be present on the type.

F#byrefの "-like" 構造体は、スタックにバインドされた値型です。A "byref-like" struct in F# is a stack-bound value type. マネージ ヒープには割り当てが行きまとい。It is never allocated on the managed heap. byref-like 構造体は、有効期間と非キャプチャに関する強力なチェックのセットで実施される、高性能プログラミングに役立ちます。A byref-like struct is useful for high-performance programming, as it is enforced with set of strong checks about lifetime and non-capture. ルールは次のとおりです。The rules are:

  • 関数パラメーター、メソッドパラメーター、ローカル変数、メソッドの戻り値として使用できます。They can be used as function parameters, method parameters, local variables, method returns.
  • クラスの静的メンバーまたはインスタンス メンバー、または通常の構造体にはできません。They cannot be static or instance members of a class or normal struct.
  • これらの関数は、どのクロージャ構造async(メソッドまたはラムダ式) でもキャプチャできません。They cannot be captured by any closure construct (async methods or lambda expressions).
  • ジェネリック パラメーターとして使用することはできません。They cannot be used as a generic parameter.

これらのルールは、使用を非常に強く制限しますが、安全な方法で高性能コンピューティングの約束を果たすために行います。Although these rules very strongly restrict usage, they do so to fulfill the promise of high-performance computing in a safe manner.

ReadOnly 構造体ReadOnly structs

属性を使用して構造体にアコーズをIsReadOnlyAttribute付けることができます。You can annotate structs with the IsReadOnlyAttribute attribute. 次に例を示します。For example:

[<IsReadOnly; Struct>]
type S(count1: int, count2: int) =
    member x.Count1 = count1
    member x.Count2 = count2

IsReadOnlyは をStruct意味しません。IsReadOnly does not imply Struct. 構造体を持つには、両方IsReadOnlyを追加する必要があります。You must add both to have an IsReadOnly struct.

この属性を使用すると、F# と C# がそれぞれとinref<'T>を扱うようにin ref知らせるメタデータが生成されます。Use of this attribute emits metadata letting F# and C# know to treat it as inref<'T> and in ref, respectively.

読み取り専用構造体の中で変更可能な値を定義すると、エラーが発生します。Defining a mutable value inside of a readonly struct produces an error.

構造体レコードと判別共用体Struct Records and Discriminated Unions

この[<Struct>]属性を使用して、レコードおよび判別共用体を構造体として表すことができます。You can represent Records and Discriminated Unions as structs with the [<Struct>] attribute. 詳細については、各記事をご覧ください。See each article to learn more.

関連項目See also