When creating a new instance of a C# 9 record by using the with keyword, I'd like to ignore some fields instead of copying them into the new instance too.
In the following example, I have a Hash property. Because it is very expensive in computation, it is only computed when needed and then cached (I have a deeply immutable record, so that hash will never change for an instance).
public record MyRecord {
// All truely immutable properties
public int ThisAndManyMoreComplicatedProperties { get; init; }
// ...
// Compute only when required, but then cache it
public string Hash {
get {
if (hash == null)
hash = ComputeHash();
return hash;
}
}
private string? hash = null;
}
When calling
MyRecord myRecord = ...;
var changedRecord = myRecord with { AnyProp = ... };
changedRecord contains the hash value from myRecord, but what I want to have is the default value null again.
Any chance to mark the hash field as "transient"/"internal"/"reallyprivate"..., or do I have to write my own copy-constructor to mimic this feature?
I found a workaround: You can (ab)use inheritance to split the copy constructor in two parts: A manual one only for
hash(in the base class) and an auto-generated one in the derived class copying all your valuable data fields.This has the additional advantage of abstracting away your hash (non-)caching logic. Here's a minimal example (fiddle):