Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 71 additions & 28 deletions docs/fsharp/language-reference/records.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@ ms.date: 12/21/2021
---
# Records (F#)

Records represent simple aggregates of named values, optionally with members. They can either be structs or reference types. They are reference types by default.
Records represent simple aggregates of named values, optionally with members. They can either be structs or reference types. They are reference types by default.

## Syntax

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

Expand Down Expand Up @@ -96,33 +98,33 @@ For example, the following code defines a `Person` and `Address` type as mutuall
```fsharp
// Create a Person type and use the Address type that is not defined
type Person =
{ Name: string
Age: int
Address: Address }
{ Name: string
Age: int
Address: Address }
// Define the Address type which is used in the Person record
and Address =
{ Line1: string
Line2: string
PostCode: string
Occupant: Person }
{ Line1: string
Line2: string
PostCode: string
Occupant: Person }
```

To create instances of both, you do the following:

```fsharp
// Create a Person type and use the Address type that is not defined
let rec person =
{
Name = "Person name"
Age = 12
Address =
{
Line1 = "line 1"
Line2 = "line 2"
PostCode = "abc123"
Occupant = person
}
}
{
Name = "Person name"
Age = 12
Address =
{
Line1 = "line 1"
Line2 = "line 2"
PostCode = "abc123"
Occupant = person
}
}
```

If you were to define the previous example without the `and` keyword, then it would not compile. The `and` keyword is required for mutually recursive definitions.
Expand All @@ -147,9 +149,9 @@ You can specify members on records much like you can with classes. There is no s

```fsharp
type Person =
{ Name: string
Age: int
Address: string }
{ Name: string
Age: int
Address: string }

static member Default =
{ Name = "Phillip"
Expand All @@ -163,9 +165,9 @@ If you use a self identifier, that identifier refers to the instance of the reco

```fsharp
type Person =
{ Name: string
Age: int
Address: string }
{ Name: string
Age: int
Address: string }

member this.WeirdToString() =
this.Name + this.Address + string this.Age
Expand All @@ -174,6 +176,47 @@ let p = { Name = "a"; Age = 12; Address = "abc123" }
let weirdString = p.WeirdToString()
```

## Accessibility Modifiers on Constructors

You can modify the accessibility of the respective properties of the record's constructor, which affects how they are accessed from outside the module. The following code example illustrates this.

```fsharp
module Person =

type Person =
private {
Name: string
Age: int
Address: string
}

let createPerson name age address =
{ Name = name; Age = age; Address = address }

let getPersonInfo (person: Person) =
$"- Name: {person.Name}\n- Age: {person.Age}\n- Address: {person.Address}"

module Main =
open Person

let person = createPerson "Phillip" 12 "123 happy fun street"

// Outside the 'Person' module, this line will cause a compiler error.
// let personName = person.Name

printfn "%s" (getPersonInfo person)
```

The output of this code is as follows:

```console
- Name: Phillip
- Age: 12
- Address: 123 happy fun street
```

For more information about accessibility modifiers, see the [Access Control](./access-control.md) article.

## Differences Between Records and Classes

Record fields differ from class fields in that they are automatically exposed as properties, and they are used in the creation and copying of records. Record construction also differs from class construction. In a record type, you cannot define a constructor. Instead, the construction syntax described in this topic applies. Classes have no direct relationship between constructor parameters, fields, and properties.
Expand Down
Loading