Records: prevent object cloning if resulting object is logically the same #8506
Unanswered
macsux
asked this question in
Language Ideas
Replies: 2 comments 40 replies
-
Records are cloned prior to any of the properties being set: var original = new Node("A");
// the following
var derived = original with { MyProperty = "A" };
// is equivalent to
var $temp = original.Clone();
$temp.MyProperty = "A";
var derived = $temp; |
Beta Was this translation helpful? Give feedback.
37 replies
-
Records are NOT guaranteed immutable: public record Node(string MyProperty)
{
private int state;
public int Change() => state++;
} And there's no way to detect if a record implementation is indeed immutable. |
Beta Was this translation helpful? Give feedback.
3 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Currently, a call to a records
with
expression always produces a new instance. This however is not optimal if all the new values passed to thewith
clause are the same as the original record. Consider the following:In certain scenarios where happens there's opportunity to reuse existing objects rather than cloning, potentially preventing significant new memory allocations. Since the two objects are immutable, returning original in place of copy should be safe.
This behaviour should probably be on an "opt-in" basis because it would require comparison of the new properties to ones on the existing object before deciding if object needs to be cloned.
A practical example where this might be useful is in code that implements a visitor pattern over immutable data structure (like Roslyn) where 90% of the tree structure could be reused and only small "branch" of nodes changed.
Implementation proposal
I'll update this as discussion below progresses
This change would require the use of upgraded compiler on both side, hence requiring that libraries that choose to use this feature re-target to newer versions of .NET.
Compiler generates a synthetic method like this on record types:
If overriden, the compiler would instead of generating the normal hidden parameter-less
<Clone>$
method, would instead one that like this:Consumer side compiler would interpret a
with
clause like this:into something logically similar to this:
Beta Was this translation helpful? Give feedback.
All reactions