Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Una estructura es un tipo de objeto compacto que puede ser más eficaz que una clase para los 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
Observaciones
Las estructuras son tipos de valor, lo que significa que se almacenan directamente en la pila o, cuando se usan como campos o elementos de matriz, insertados en el tipo primario. A diferencia de las clases y registros, las estructuras tienen semántica de paso a valor. Esto significa que son útiles principalmente para pequeños agregados de datos a los que se accede y se copian con frecuencia.
En la sintaxis anterior, se muestran dos formularios. La primera no es la sintaxis ligera, pero se usa con frecuencia porque, al usar las struct palabras clave y end , puede omitir el StructAttribute atributo , que aparece en el segundo formulario. Puede abreviar StructAttribute solo Structa .
El type-definition-elements-and-members de la sintaxis anterior representa declaraciones y definiciones de miembro. Las estructuras pueden tener constructores y campos mutables e inmutables, y pueden declarar miembros e implementaciones de interfaz. Para obtener más información, vea Miembros.
Las estructuras no pueden participar en la herencia, no pueden contener enlaces ni do contener let de forma recursiva campos de su propio tipo (aunque pueden contener celdas de referencia que hacen referencia a su propio tipo).
Dado que las estructuras no permiten let enlaces, debe declarar campos en estructuras mediante la val palabra clave . La val palabra clave define un campo y su tipo, pero no permite la inicialización. En su lugar, val las declaraciones 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 val las declaraciones se anoten con el DefaultValue atributo . Las estructuras que tienen un constructor definido siguen admitiendo la inicialización cero. Por lo tanto, el DefaultValue atributo es una declaración de que este valor cero es válido para el campo. Los constructores implícitos para estructuras no realizan ninguna acción porque let no se permiten enlaces en do el tipo, pero los valores de parámetro de constructor implícitos pasados están disponibles como campos privados.
Los constructores explícitos pueden implicar la inicialización de valores de campo. Cuando tiene una estructura que tiene un constructor explícito, todavía admite la inicialización cero; sin embargo, no se usa el DefaultValue atributo en las val declaraciones porque entra en conflicto con el constructor explícito. Para obtener más información sobre val las declaraciones, vea Campos explícitos: la val palabra clave .
Los atributos y los modificadores de accesibilidad se permiten en estructuras y siguen las mismas reglas que las de otros tipos. Para obtener más información, vea Atributos y control de acceso.
En los ejemplos de código siguientes se muestran las definiciones de 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 puedan cumplir la semántica similar a byrefla siguiente: consulte Byrefs para obtener más información. Esto se hace con el 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 "byrefsimilar" en F# es un tipo de valor enlazado a la pila. Nunca se asigna en el montón administrado. Una byrefestructura similar 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 estructura normal.
- No se pueden capturar mediante ninguna construcción de cierre (
asyncmétodos o expresiones lambda). - No se pueden usar como parámetro genérico.
Aunque estas reglas restringen muy fuertemente el uso, lo hacen para cumplir la promesa de informática de alto rendimiento de una manera segura.
Structs ReadOnly
Puede anotar estructuras con el IsReadOnlyAttribute atributo . 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 IsReadOnly estructura.
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 de solo lectura genera un error.
Registros de estructura y uniones discriminadas
Puede representar registros y uniones discriminadas como estructuras con el [<Struct>] atributo . Consulte cada artículo para obtener más información.