Syntax
public record RecordName(type Prop1, type Prop2);Examples
Basic Record
A record automatically gets a constructor, properties, value equality, and ToString.
public record Point(int X, int Y);
Point p1 = new Point(3, 4);
Console.WriteLine(p1.X); // 3 - auto-generated property
Console.WriteLine(p1); // Point { X = 3, Y = 4 } - auto ToString()
Point p2 = new Point(3, 4);
Console.WriteLine(p1 == p2); // true - value equality, unlike a class
Console.WriteLine(p1.Equals(p2)); // trueNon-Destructive Mutation with with
The with expression creates a new record with some properties changed, leaving the original untouched.
public record Point(int X, int Y);
Point original = new Point(3, 4);
Point moved = original with { X = 10 };
Console.WriteLine(original); // Point { X = 3, Y = 4 } - unchanged
Console.WriteLine(moved); // Point { X = 10, Y = 4 }Record with Additional Members
Records can still define their own methods alongside the automatically generated ones.
public record Rectangle(double Width, double Height)
{
public double Area => Width * Height;
public bool IsSquare => Width == Height;
}
Rectangle r = new Rectangle(5, 5);
Console.WriteLine(r.Area); // 25
Console.WriteLine(r.IsSquare); // trueDeconstruction
Records automatically support deconstruction into separate variables.
public record Point(int X, int Y);
Point p = new Point(3, 4);
var (x, y) = p; // deconstructs automatically
Console.WriteLine($"x={x}, y={y}");Best practices
- Use records for simple, immutable data carriers (DTOs, value objects) instead of hand-writing a full class with Equals, GetHashCode, and ToString
- Use the with expression to create modified copies instead of mutating a record in place, which keeps the immutability guarantees intact
- Prefer records over classes whenever value-based equality (comparing by data, not reference) is what you actually want
- Remember records are reference types stored on the heap like classes - "record" describes their equality/immutability behavior, not their memory location (use record struct for a value-type record)
At a glance
- Purpose
- Applications on the .NET platform
- File extension
- .cs
- Runs in
- .NET runtime
- Usually used with
- .NET SDK and libraries
Specifications & further reading
Related C# documentation
A class is a blueprint for creating objects, bundling related data (fields/properties) and behavior (methods) together. C# is a fully object-oriented language - every application has at least one class, typically with a Main method as its entry point. An object is a specific instance of a class, created with the new keyword, with its own independent copy of the class's instance data.Constructors
A constructor is a special method that runs automatically when an object is created with new, used to initialize the object's state. A constructor shares its name with the class and has no return type. C# supports constructor overloading (multiple constructors with different parameter lists) and constructor chaining with this(...), where one constructor calls another in the same class to avoid duplicating initialization logic.Properties (get/set)
Properties are C#'s idiomatic way to expose class data through accessor-like syntax while still allowing controlled access via get and set. Unlike a plain public field, a property can validate a value before it's set, compute a value on the fly, or restrict access to read-only. Auto-implemented properties (using { get; set; } with no body) provide a concise shorthand when no custom logic is needed.Access Modifiers
Access modifiers control the visibility of classes, fields, methods, and properties from other parts of a program. C# provides public (accessible from anywhere), private (accessible only within the declaring class - the default for class members), protected (accessible within the class and its subclasses), internal (accessible only within the same assembly/project), and combinations like protected internal and private protected.