I am reading Joseph Albahari's book "C# 10 in a Nutshell", it talks about "Nondesctructive mutation for anonymous types" but I don't even know what mutation is, on google all I could find was "Mutation testing" or "What is Nondesctructive mutation?" which they always end up in as a side feature to record type. Could someone please break it down to me? Some examples would be much appreciated!
To mutate (in the sense used in "nondesctructive mutation for anonymous types") just means to change the state of an object. Here is a simple example:
var sb = new StringBuilder("Hello");
// We mutate the object referenced by sb, so that it contains
// "Hello!" rather than "Hello".
sb.Append("!")
Console.WriteLine(sb.ToString()); // prints Hello!
StringBuilder
is a mutable class. Other classes, such as String
, are immutable:
var s = "Hello";
// The following expression returns a *new* string "hello",
// but does not mutate the original string itself.
s.ToLower();
Console.WriteLine(s); // still prints Hello
So, what do we do if we want to mutate the contents of an immutable class, for example, to lowercase the contents of a string? We create a new object that contains the modified version. This is what string.ToLower
does:
var s1 = "Hello";
var s2 = s1.ToLower();
Console.WriteLine(s1); // prints Hello
Console.WriteLine(s2); // prints hello
This is called non-destructive mutation: The original string s1
still exists, it has not been destroyed. On the other hand, sb.Append("!")
in the very first example was destructive: The version of sb
containing Hello
(without exclamation mark) is no longer accessible.
(Obviously, you can re-use the same variable name when lowercasing a string, e.g. s = s.ToLower()
. But that does not change the fact that ToLower
creates a new object rather than modifying the old one in-place. s = ...
ensures that the variable s
points to the new object afterwards.)
So, what does this have to do with anonymous types? Anonymous types in C# are immutable:
var myObject = new { A = 1, B = 2 };
myObject.B = 3; // <- yields a compile-time error
C#9 introduced the with
keyword, which allows you to create a new object which is an exact copy of the original object, except for the values you want to change:
var o1 = new { A = 1, B = 2 };
var o2 = o1 with { B = 3 };
// o1: A = 1, B = 2
// o2: A = 1, B = 3
© 2022 - 2024 — McMap. All rights reserved.