What is mutation in C#?

Viewed 145

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!

1 Answers

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
Related