Estructuras

Una estructura es un tipo de objeto compacto que puede ser más eficaz que una clase en tipos que tienen una pequeña cantidad de datos y un comportamiento simple.

Sintaxis

[ 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

Comentarios

Las estructuras son tipos de valor, lo que significa que se almacenan directamente en la pila o, cuando se utilizan como campos o tipo de elementos de la matriz, alineados en el tipo primario. A diferencia de los registros y las clases, las estructuras tienen semántica de paso por valor. Esto significa que son útiles principalmente para pequeños agregados de datos a los que accede y que se copian con frecuencia.

En la sintaxis anterior, se muestran dos formularios. La primera no es la sintaxis ligera; sin embargo, se utiliza frecuentemente porque, cuando se usan las palabras clave struct y end, se puede omitir el atributo StructAttribute, que aparece en el segundo formulario. StructAttribute se puede abreviar como Struct.

El type-definition-elements-and-members en la sintaxis anterior, representa definiciones y declaraciones de miembros. Las estructuras pueden tener constructores y campos mutables e inmutables, y pueden declarar implementaciones de interfaces y miembros. Para más información, consulte Miembros.

Las estructuras no pueden participar en la herencia, no pueden contener enlaces let ni do, y no puede contener de forma recursiva campos de su propio tipo (aunque pueden contener celdas de referencia que hagan referencia a su propio tipo).

Dado que las estructuras no permiten enlaces let, debe declarar campos en estructuras mediante el uso de la palabra clave val. La palabra clave val define un campo y su tipo, pero no permite la inicialización. En su lugar, las declaraciones val se inicializan en cero o null. Por este motivo, las estructuras que tienen un constructor implícito (es decir, los parámetros que se proporcionan inmediatamente después del nombre de la estructura en la declaración) requieren que las declaraciones val se anoten con el atributo DefaultValue. Las estructuras que tienen un constructor definido todavía admiten la inicialización en cero. Por lo tanto, el atributo DefaultValue es una declaración de que ese valor cero es válido para el campo. Los constructores implícitos de las estructuras no realizan ninguna acción porque los enlaces let y do no están permitidos en el tipo, pero los valores de parámetro de constructor implícito pasados están disponibles como campos privados.

Los constructores explícitos podrían implicar la inicialización de los valores de campo. Cuando se tiene una estructura con un constructor explícito, se admite la inicialización en cero; sin embargo, no se utiliza el atributo DefaultValue en las declaraciones val porque entra en conflicto con el constructor explícito. Para obtener más información sobre las declaraciones val, consulte Campos explícitos: La palabra clave val.

Los atributos y modificadores de accesibilidad están permitidos en las estructuras y siguen las mismas reglas que las de otros tipos. Para más información, consulte Atributos y Control de acceso.

Los siguientes ejemplos de código ilustran las definiciones de la estructura.

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

Estructuras ByRefLike

Puede definir sus propias estructuras que pueden cumplir la semántica similar a byref: consulte Byrefs para obtener más información. Esto se realiza a través del atributo 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 no implica Struct. Ambos deben estar presentes en el tipo.

Una estructura «similar abyref» en F# es un tipo de valor enlazado a la pila. Nunca se asigna en el montón administrado. Una estructura similiar a byref es útil para la programación de alto rendimiento, ya que se aplica con un conjunto de comprobaciones seguras sobre la duración y la no captura. Las reglas son:

  • Se pueden usar como parámetros de función, parámetros de método, variables locales, devoluciones de método.
  • No pueden ser miembros estáticos o de instancia de una clase o una estructura normal.
  • No se pueden capturar mediante ninguna construcción de cierre (métodos async o expresiones lambda).
  • No se pueden usar como parámetro genérico.

Aunque estas reglas restringen fuertemente el uso, lo hacen para cumplir la promesa de informática de alto rendimiento de una manera segura.

Estructuras ReadOnly

Puede anotar estructuras con el atributo IsReadOnlyAttribute. Por ejemplo:

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

IsReadOnly no implica Struct. Debe agregar ambos para tener una estructura IsReadOnly.

El uso de este atributo emite metadatos que permiten que F# y C# sepan tratarlos como inref<'T> y in ref, respectivamente.

La definición de un valor mutable dentro de una estructura readonly genera un error.

Registros de estructura y uniones discriminadas

Puede representar registros y uniones discriminadas como estructuras con el atributo [<Struct>]. Consulte cada artículo para obtener más información.

Vea también