Partager via


Structures

Une structure est un type d’objet compact qui peut être plus efficace qu’une classe pour les types qui ont une petite quantité de données et un comportement simple.

Syntaxe

[ 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

Remarques

Les structures sont des types valeur, ce qui signifie qu’elles sont stockées directement sur la pile ou, lorsqu’elles sont utilisées en tant que champs ou éléments de tableau, inline dans le type parent. Contrairement aux classes et aux enregistrements, les structures ont une sémantique pass-by-value. Cela signifie qu’elles sont utiles principalement pour les petits agrégats de données qui sont accessibles et copiés fréquemment.

Dans la syntaxe précédente, deux formulaires sont affichés. La première n’est pas la syntaxe légère, mais elle est néanmoins fréquemment utilisée car, lorsque vous utilisez les mots clés et end les struct mots clés, vous pouvez omettre l’attributStructAttribute, qui apparaît dans le deuxième formulaire. Vous pouvez abrégée StructAttribute à juste Struct.

Le type-definition-elements-and-members dans la syntaxe précédente représente les déclarations et définitions de membre. Les structures peuvent avoir des constructeurs et des champs mutables et immuables, et ils peuvent déclarer des membres et des implémentations d’interface. Pour plus d’informations, consultez Membres.

Les structures ne peuvent pas participer à l’héritage, ne peuvent pas contenir ou do liaisons, et ne peuvent pas contenir de manière récursive des champs de leur propre type (bien qu’elles puissent contenir let des cellules de référence qui référencent leur propre type).

Étant donné que les structures n’autorisent let pas les liaisons, vous devez déclarer des champs dans des structures à l’aide du val mot clé. Le val mot clé définit un champ et son type, mais n’autorise pas l’initialisation. Au lieu de cela, val les déclarations sont initialisées à zéro ou null. Pour cette raison, les structures qui ont un constructeur implicite (autrement dit, les paramètres qui sont donnés immédiatement après le nom de la structure dans la déclaration) nécessitent que val les déclarations soient annotées avec l’attribut DefaultValue . Les structures qui ont un constructeur défini prennent toujours en charge l’initialisation zéro. Par conséquent, l’attribut DefaultValue est une déclaration indiquant qu’une telle valeur zéro est valide pour le champ. Les constructeurs implicites pour les structures n’effectuent aucune action, car let et do les liaisons ne sont pas autorisées sur le type, mais les valeurs de paramètre de constructeur implicite transmises sont disponibles en tant que champs privés.

Les constructeurs explicites peuvent impliquer l’initialisation des valeurs de champ. Lorsque vous avez une structure qui a un constructeur explicite, elle prend toujours en charge l’initialisation zéro ; Toutefois, vous n’utilisez pas l’attribut DefaultValue sur les val déclarations, car il est en conflit avec le constructeur explicite. Pour plus d’informations sur les val déclarations, consultez Champs explicites : Le val mot clé.

Les attributs et les modificateurs d’accessibilité sont autorisés sur les structures et suivent les mêmes règles que celles des autres types. Pour plus d’informations, consultez Attributs et contrôle d’accès.

Les exemples de code suivants illustrent les définitions de structure.

// 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

Structs ByRefLike

Vous pouvez définir vos propres structs qui peuvent adhérer à byrefdes sémantiques similaires : consultez Byrefs pour plus d’informations. Pour ce faire, utilisez l’attribut IsByRefLikeAttribute :

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 n’implique Structpas . Les deux doivent être présents sur le type.

Un struct «byref like » en F# est un type de valeur lié à la pile. Il n’est jamais alloué sur le tas managé. Un byrefstruct semblable est utile pour la programmation hautes performances, car il est appliqué avec un ensemble de vérifications fortes sur la durée de vie et la non-capture. Les règles sont les suivantes :

  • Ils peuvent être utilisés comme paramètres de fonction, paramètres de méthode, variables locales, retours de méthode.
  • Ils ne peuvent pas être des membres statiques ou d’instance d’une classe ou d’un struct normal.
  • Ils ne peuvent pas être capturés par une construction de fermeture (async méthodes ou expressions lambda).
  • Ils ne peuvent pas être utilisés comme paramètre générique.

Bien que ces règles restreignent très fortement l’utilisation, elles le font pour répondre à la promesse d’un calcul hautes performances de manière sécurisée.

Structs ReadOnly

Vous pouvez annoter des structs avec l’attribut IsReadOnlyAttribute . Par exemple:

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

IsReadOnly n’implique Structpas . Vous devez ajouter les deux pour avoir un IsReadOnly struct.

L’utilisation de cet attribut émet des métadonnées permettant à F# et C# de le traiter comme inref<'T> et in ref, respectivement.

La définition d’une valeur mutable à l’intérieur d’un struct en lecture seule génère une erreur.

Struct Records and Discriminated Unions

Vous pouvez représenter des enregistrements et des unions discriminées en tant que structs avec l’attribut [<Struct>] . Consultez chaque article pour en savoir plus.

Voir aussi