- Published on
C# Records and the with Keyword — Update without mutation
- Authors
- Name
- Mathias Hove
- @mathias_hove
with
Keyword for C# Records
The C# Records is a very useful feature that has been added to the language. Been playing around with it a lot recently and stumbled upon the with keyword. It is very useful when you need to update a few properties in an immutable object, without changing the original object. This approach is also known as non-destructive mutation.
So, why does it matter?
With records, the data is immutable — once you create the object, its values stay fixed. This characteristic helps maintain strong data integrity.
Example without with
:
public record Product(string Name, decimal Price, string Category);
var original = new Product("Laptop", 999.99m, "Electronics");
// Old way: recreate with updated values
var updated = new Product(
original.Name,
900.99m,
original.Category
);
With with
, it’s much simpler:
var updated = original with { Price = 899.99m };
The compiler clones the existing object using a hidden method, copies all property values, and applies the specified changes. The original object remains the same, due to it being immutable
Updating multiple properties.
var clearanceItem = original with
{
Price = 749.99m,
Category = "Clearance"
};
Changing nested records.
public record Address(string Street, string City);
public record Customer(string Name, Address Location);
var customer = new Customer("Jane", new Address("123 Main St", "Springfield"));
var movedCustomer = customer with
{
Location = customer.Location with { City = "Shelbyville" }
};
Use cases
For DDD, value objects are immutable. The with keyword makes updates very simple.
public record class Price
{
public decimal Amount { get; init; }
public string Currency { get; init; }
public Price(decimal amount, string currency)
{
if (amount < 0)
throw new ArgumentOutOfRangeException(nameof(amount), "Amount must be positive.");
if (string.IsNullOrWhiteSpace(currency))
throw new ArgumentException("Currency is required.", nameof(currency));
Amount = amount;
Currency = currency;
}
}
var price = new Price(Amount: 100m, Currency: "USD");
var updatedPrice = price with { Amount = 120m };
Limitations
- Works only on records (class or struct)
- Properties must have
init
orset
accessors - You cannot use it on normal c# classes. Then you would have to write your own clone logic.
- Each
with
call will create a new object. Be aware of the overhead for performance-sensitive code.
Summary: The with keyword is awesome. It makes working with immutable records straightforward. It is one of the many new c# features that make the language modern and up to date.