Glossary / with expressions

with expressions

A with expression creates a copy of a record or supported struct value and applies specified member changes to that copy. It supports nondestructive updates while preserving the original value, but the copy is shallow and the feature's behavior depends on the type's copy semantics and accessible init/set members.

Record and struct forms

public record User(string Name, string City);
var user = new User("Ada", "London");
var moved = user with { City = "Budapest" };

For record classes, with performs a shallow copy of the object and initializes selected members on the copy. The original object remains unchanged, but references inside both copies are shared unless explicitly replaced. Record structs copy the value and apply updates to the copied value. C# also supports with on other struct types under language rules when they provide suitable accessible members and copy semantics; do not assume it is exclusive to records in newer language versions.

with is not deep cloning and does not guarantee immutability. Init-only properties limit when members can be assigned; mutable referenced collections can still change through either instance. Custom copy constructors and record inheritance affect exact copy behavior.

Engineering guidance

Use for immutable-style state transitions and DTO updates. Be explicit about nested mutable members and copy cost for large structs. Prefer a dedicated copy/transform method when updates require validation, deep cloning, or complex invariants. Test equality and nested aliasing after updates.

Interview questions

  1. Does with mutate the original? It creates a copy and applies changes to that copy.
  2. Is the copy deep? No, referenced members are generally shared unless replaced/copied explicitly.
  3. Do all types support with? Records do; supported struct forms also exist depending on language-version rules.
  4. Does with imply immutable data? No; mutability can remain through settable properties or referenced objects.
  5. When use a method instead? When updates need validation, complex invariants, or deep-copy semantics.

References