Share via


Registros (F#)

Los registros representan agregados simples de valores con nombre, opcionalmente con miembros.

[ attributes ]
type [accessibility-modifier] typename = { 
    [ mutable ] label1 : type1;
    [ mutable ] label2 : type2;
    ...
    }
    member-list

Comentarios

En la sintaxis anterior, typename es el nombre del tipo de registro, label1 y label2 son nombres de valores, denominados etiquetas, mientras que type1 y type2 son los tipos de estos valores. member-list es la lista opcional de miembros para el tipo.

A continuación figuran algunos ejemplos.

type Point = { x : float; y: float; z: float; }
type Customer = { First : string; Last: string; SSN: uint32; AccountNumber : uint32; }

Cuando cada etiqueta se encuentra en una línea independiente, el signo de punto y coma es opcional.

Puede establecer valores en las expresiones denominadas expresiones de registro. El compilador deduce el tipo a partir de las etiquetas utilizadas (si las etiquetas se diferencian lo suficiente de las de los demás tipos de registro). La expresión de registro va entre llaves ({}). El siguiente código muestra una expresión de registro que inicializa un registro con tres elementos de tipo float con las etiquetas x, y y z.

let mypoint = { x = 1.0; y = 1.0; z = -1.0; }

No utilice la forma abreviada si existe la posibilidad de que haya otro tipo que tenga las mismas etiquetas.

type Point = { x : float; y: float; z: float; }
type Point3D = { x: float; y: float; z: float }
// Ambiguity: Point or Point3D?
let mypoint3D = { x = 1.0; y = 1.0; z = 0.0; }

Las etiquetas del tipo que se ha declarado más recientemente tienen precedencia sobre las del tipo declarado con anterioridad; así pues, en el ejemplo anterior, se infiere que mypoint3D es Point3D. Se puede especificar explícitamente el tipo de registro, como en el siguiente código.

let myPoint1 = { Point.x = 1.0; y = 1.0; z = 0.0; }

Se pueden definir métodos para los tipos de registro de la misma manera que para los tipos de clase.

Crear registros mediante expresiones de registro

Puede inicializar los registros utilizando las etiquetas que se definen en el registro. Una expresión que hace esto se denomina expresión de registro. La expresión de registro debe ir entre llaves y se utiliza el signo de punto y coma como delimitador.

En el siguiente ejemplo, se muestra cómo crear un registro.

type MyRecord = {
    X: int;
    Y: int;
    Z: int 
    }

let myRecord1 = { X = 1; Y = 2; Z = 3; }

El uso del signo de punto y coma después del último campo en la expresión de registro y en la definición de tipo es opcional, independientemente de si todos los campos están en una línea.

Al crear un registro, se deben proporcionar valores para todos los campos. No se puede hacer referencia a los valores de otros campos en la expresión de inicialización de ningún campo.

En el código siguiente, se realiza la inferencia de tipos de myRecord2 a partir de los nombres de los campos. Opcionalmente, se puede especificar el nombre de tipo explícitamente.

let myRecord2 = { MyRecord.X = 1; MyRecord.Y = 2; MyRecord.Z = 3 }

Otra forma de construcción de registro puede resultar útil cuando se tiene que copiar un registro existente y, posiblemente, cambiar los valores de algunos campos. En la siguiente línea de código se muestra cómo hacerlo:

let myRecord3 = { myRecord2 with Y = 100; Z = 2 }

Esta forma de expresión de registro se denomina expresión de registro de copia y actualización.

De forma predeterminada, los registros son inmutables; sin embargo, es fácil crear registros modificados usando una copia y una expresión de actualización. También se puede especificar explícitamente un campo mutable.

type Car = {
    Make : string
    Model : string
    mutable Odometer : int
    }
let myCar = { Make = "Fabrikam"; Model = "Coupe"; Odometer = 108112 }
myCar.Odometer <- myCar.Odometer + 21

Coincidencia de modelos con registros

Se pueden utilizar registros con la coincidencia de modelos. Se pueden especificar algunos campos explícitamente y proporcionar variables para otros campos que se asignarán cuando haya una coincidencia. En el siguiente ejemplo código se muestra cómo hacerlo.

type Point3D = { x: float; y: float; z: float }
let evaluatePoint (point: Point3D) =
    match point with
    | { x = 0.0; y = 0.0; z = 0.0 } -> printfn "Point is at the origin."
    | { x = xVal; y = 0.0; z = 0.0 } -> printfn "Point is on the x-axis. Value is %f." xVal
    | { x = 0.0; y = yVal; z = 0.0 } -> printfn "Point is on the y-axis. Value is %f." yVal
    | { x = 0.0; y = 0.0; z = zVal } -> printfn "Point is on the z-axis. Value is %f." zVal
    | { x = xVal; y = yVal; z = zVal } -> printfn "Point is at (%f, %f, %f)." xVal yVal zVal

evaluatePoint { x = 0.0; y = 0.0; z = 0.0 }
evaluatePoint { x = 100.0; y = 0.0; z = 0.0 }
evaluatePoint { x = 10.0; y = 0.0; z = -1.0 }

El resultado de este código es el siguiente:

Point is at the origin.
Point is on the x-axis. Value is 100.000000.
Point is at (10.000000, 0.000000, -1.000000).

Diferencias entre los registros y las clases

Los campos de registro se difieren de las clases en que se exponen automáticamente como propiedades y se utilizan en la creación y la copia de registros. La construcción de registros también difiere de la construcción de clases. En un tipo de registro, no se puede definir un constructor. En cambio, se aplica la sintaxis de construcción descrita en este tema. Las clases no presentan ninguna relación directa entre los parámetros, campos y propiedades de constructor.

Al igual que los tipos union y structure, los registros tienen una semántica de igualdad estructural. Las clases tienen una semántica de igualdad de referencia. En el siguiente ejemplo de código se muestra este caso.

type RecordTest = { X: int; Y: int }
let record1 = { X = 1; Y = 2 }
let record2 = { X = 1; Y = 2 }
if (record1 = record2) then
    printfn "The records are equal."
else
    printfn "The records are unequal."

Si se escribiese el mismo código con clases, los dos objetos de clase serían desiguales porque los dos valores representarían dos objetos en el montón y solo se compararían las direcciones (a menos que el tipo de clase reemplace el método System.Object.Equals).

Vea también

Referencia

Clases (F#)

Coincidencia de modelos [F#]

Otros recursos

Tipos en F#

Referencia del lenguaje F#

Historial de cambios

Fecha

Historial

Motivo

Mayo de 2010

Se han mejorado algunos ejemplos de código.

Mejora de la información.