C#中的变异是什么?

5

我正在阅读Joseph Albahari的《C# 10入门指南》一书,它谈到了“匿名类型的无损突变”,但我甚至不知道突变是什么,在Google上我只能找到“突变测试”或“什么是无损突变?”这些内容总是作为记录类型的附带功能。请问有人可以给我解释一下吗?一些例子会更加感激!


1
在这种情况下,“变异”只是指“改变对象的状态”。你已经理解了可变和不可变对象之间的区别吗?“非破坏性变异”是一种使用不可变类型进行类似于变异的技术。 - Heinzi
1
https://www.stevefenton.co.uk/2020/05/csharp-9-non-destructive-mutation/ - Rand Random
@Heinzi,所以变异与可变性有关?那么,变异测试基本上是“测试对象类型是否更改”还是“对象的值是否更改”? - Cenko
不,"变异测试"是完全不同的东西。变异测试之所以被称为变异测试,是因为它涉及到对代码进行变异(即改变)。而"匿名类型的非破坏性变异"则是指对对象进行变异(即改变)。在遗传学中(举一个完全无关的第三个例子),"变异"指的是基因组的变化。这就是英语的美妙之处:单词没有上下文是毫无意义的。 - Heinzi
1个回答

9

突变(在“匿名类型的非破坏性突变”中使用的意义上)仅表示更改对象的状态。 这里是一个简单的例子:

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 是一个可变的类。其他类,例如 String,是不可变的:

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

那么,如果我们想要改变一个不可变类的内容,例如将字符串的内容转换为小写,我们会怎么做呢?我们创建一个新对象来包含修改后的版本。这就是string.ToLower所做的事情:

var s1 = "Hello";
var s2 = s1.ToLower();

Console.WriteLine(s1);   // prints Hello
Console.WriteLine(s2);   // prints hello

这被称为“非破坏性变异”:原始字符串 s1 仍然存在,它并没有被销毁。另一方面,在第一个示例中的 sb.Append("!") 是“破坏性”的:包含没有感叹号的 Hellosb 版本不再可访问。
(显然,您可以在将字符串转换为小写时重用相同的变量名称,例如 s = s.ToLower()。但是,这并不改变 ToLower 创建新对象而不是就地修改旧对象的事实。 s = ... 确保变量 s 在之后指向新对象。)
那么,这与匿名类型有什么关系?C# 中的匿名类型是不可变的:
var myObject = new { A = 1, B = 2 };

myObject.B = 3;   // <- yields a compile-time error

C#9 引入了 with 关键字,它允许你创建一个新对象,该对象是原始对象的精确复制,除了你想要更改的值之外。
var o1 = new { A = 1, B = 2 };
var o2 = o1 with { B = 3 };
    
// o1: A = 1, B = 2
// o2: A = 1, B = 3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接