How it works
A readonly record struct describes a value with generated record equality and restricted mutation. Point is small: two integers fully describe it. Assigning origin to stored copies that value. No separately allocated Point object is needed to explain the assignment, and changing which value one variable holds does not update the other variable.
The with expression constructs a modified copy using the original X coordinate plus five. The original remains two, three; the shifted point is seven, three. Equality between origin and stored succeeds because their components match. This is useful for coordinates, ranges, and other compact values whose identity is their contents.
Readonly applies to the struct's own state. If a readonly struct contains a reference to a mutable object, that referenced object can still change. This lesson deliberately uses integers so that its immutability boundary is easy to see. Value type and deep immutable object graph are not interchangeable descriptions.
A struct also always has a default value. For Point the default coordinates are zero and zero. That may be meaningful, but for another domain type an all-default value could violate an intended rule. Constructor validation alone cannot prevent every default struct value from existing, so consider how the API should handle it.
Practice by adding a Move function accepting a Point and two offsets, returning a new Point. Verify that repeated moves leave the initial point unchanged. Add tests for zero offsets, negative coordinates, and equality between two independently constructed points with the same coordinates.
Choose a struct because the value model fits, not because every struct is automatically faster than a class. Large values can be expensive to copy, and boxing can allocate when a value is used through object or an interface. First make the semantics clear; measure a real workload before making performance claims.
A working example
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
var origin = new Point(2, 3);
var shifted = origin with { X = origin.X + 5 };
var stored = origin;
Console.WriteLine($"{origin.X},{origin.Y}");
Console.WriteLine($"{shifted.X},{shifted.Y}");
Console.WriteLine(origin == stored);
readonly record struct Point(int X, int Y);
Expected output
2,3 7,3 True
The assignment copies the point value; with constructs another value.