ser*_*0ne 16 c# record immutability
我被教导结构应该几乎总是不可变的,因此记录类与记录结构的这种不寻常行为让我措手不及。
使用记录类...
record class Person(string FirstName, string LastName);
Person p = new("John", "Smith");
p.FirstName = "Jack" // Not allowed!
Run Code Online (Sandbox Code Playgroud)
使用记录结构...
record struct Person(string FirstName, string LastName);
Person p = new("John", "Smith");
p.FirstName = "Jack" // Fine!
Run Code Online (Sandbox Code Playgroud)
使用只读记录结构...
readonly record struct Person(string FirstName, string LastName);
Person p = new("John", "Smith");
p.FirstName = "Jack" // Now allowed!
Run Code Online (Sandbox Code Playgroud)
为什么非readonly记录结构默认是可变的,为什么相同的行为不适用于记录类?
编辑:我想我在这里问的是,为什么语法......很奇怪?
例如,看起来更合乎逻辑:
record class-具有值语义的可变引用类型。readonly record class-具有值语义的不可变引用类型。record struct-具有值语义的可变值类型。readonly record struct-具有值语义的不可变值类型。Rya*_*son 14
直接取自 Microsoft MVP 工程师 \xc4\xb0lkay \xc4\xb0lknur:
\n\n\n\n大多数生成的代码看起来与记录类相似。\n但是,记录结构和记录类之间有一个区别。\n 默认情况下,记录结构中生成的属性是可变的。这个决定背后的原因是为了与元组保持一致。元组就像具有相似功能的匿名记录结构。\n 另一方面,结构体可变性并不像类可变性那样受到同样程度的关注。这就是 C# 团队决定让记录结构属性默认可变的原因。但是,如果您需要不可变的记录结构,则可以使用 readonly 关键字。
\n
小智 7
如果您使用位置语法来定义 a record class,它的属性是不可变的
record class Point(int X, int Y);
Run Code Online (Sandbox Code Playgroud)
它默认具有属性附件{get; init;}
如果您以传统方式声明这一点(没有位置参数),您可以指定您的属性访问器:
record class Point
{
int X {get; set;}
int Y {get; set;}
}
Run Code Online (Sandbox Code Playgroud)
您可以混合搭配这两种样式,但请记住,如果您提供任何位置参数,它们将成为自动实现的构造函数上的参数,并且不会设置任何其他属性。
我意识到这实际上并不能回答为什么这种行为存在的问题,我只是希望阅读本文的人不会得出record class不可改变的结论。