liveBook · Manning

Record

As explained in F# in Action: A Revised Edition of Get Programming with F#

A C# record is a reference or value type designed primarily for modeling data with compiler-supported value-based equality and concise initialization syntax.

A record models related data as a named, formally defined product type. Where a tuple groups values by position, a record gives every field a name, making domain shapes such as customers, addresses, and orders easier to read, pass around, and evolve. section 5.1 section 5.3

Figure 5.1 Illustrating product (AND) and sum (OR) types. A soccer player has a name, age, and a team, but their position on the field is either forward, midfield, or defense.

Product types combine facts with AND: a player has a name, age, and team. Sum types instead represent alternatives with OR. section 5.1

Define a record before creating it, then supply every field when constructing a value. Read fields through dot notation. The compiler checks field names and types, and can often infer the record type from the fields used. section 5.3.1 section 5.3.2

Define and use a person record

type Person = { FirstName : string LastName : string Age : int } let isaac = { FirstName = "Isaac" LastName = "Abraham" Age = 42 } let fullName = $"{isaac.FirstName} {isaac.LastName}" section 5.3.1

Record fields are immutable by default. To represent a changed state, copy an existing value with copy-and-update syntax and replace only the needed fields. Equality is structural and deep: records whose fields match compare equal. section 5.3.2

Copy an address with selected changes

let addressInDE = { theAddress with Town = "Berlin" Country = "DE" } section 5.3.2

Use records when the data shape has a meaningful name and is expected to live beyond a small local calculation:

  • Choose records for everyday data modeling and public API definitions; use tuples for short-lived, simple groupings. section 5.5
  • Compose records from other records, tuples, lists, and unions to describe nested or alternative domain data. section 5.3.1 section 8.4.3
  • Keep behavior in functions and modules rather than treating a record as a class with embedded behavior. section 10.1.2
  • Pattern-match only the fields relevant to a decision when named patterns improve readability over tuple matching. section 8.1.4

Records compile to .NET classes with getter-only properties and a constructor requiring every field. They can be created and consumed from C#. A [<Struct>] attribute makes a record a value type, but that choice should be performance-tested. section 5.3.3 section 11.2.1

For web input, a simple record can mirror raw JSON with primitive fields. Map that record through validation functions into a richer domain type, returning errors separately from successful handling. section 13.2.7

How F# in Action: A Revised Edition of Get Programming with F# covers it

How deep it goes
Explains declaration, construction, inference, updates, equality, pattern matching, composition, and .NET representation; defers uncommon recursive-record use.
Examples
Demonstrates Person and Address values, customer and supplier composition, loan eligibility matching, and raw JSON validation records.
What it assumes
Introduces records after primitive and built-in .NET types, assuming familiarity with basic values while defining product-type modeling.
What you can do after
Build it from scratch as typed, immutable domain data, then update, compare, match, compose, and expose it to C#.
How it connects
Connects records to tuples, anonymous records, discriminated unions, lists, pattern matching, modules, immutability, and JSON validation.

Also explained in

Compare how 12 books explain record →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of F# in Action: A Revised Edition of Get Programming with F#. The section links point to the parts of the book it draws on.