繁体   English   中英

C# - 为什么默认情况下记录类是不可变的,但记录结构不是?

[英]C# - Why are record classes immutable by default, but record structs are not?

我被告知结构应该几乎总是不可变的,所以记录类与记录结构的这种不寻常行为让我措手不及。

使用一条记录class...

record class Person(string FirstName, string LastName);
Person p = new("John", "Smith");
p.FirstName = "Jack" // Not allowed!

使用记录结构...

record struct Person(string FirstName, string LastName);
Person p = new("John", "Smith");
p.FirstName = "Jack" // Fine!

使用只读记录结构...

readonly record struct Person(string FirstName, string LastName);
Person p = new("John", "Smith");
p.FirstName = "Jack" // Now allowed!

为什么readonly记录结构在默认情况下是可变的,为什么相同的行为不适用于记录类?

编辑:我想我在这里问的是,为什么语法......很奇怪?

例如,它看起来更符合逻辑:

  • record class - 具有值语义的可变引用类型。
  • readonly record class - 具有值语义的不可变引用类型。
  • record struct - 具有值语义的可变值类型。
  • readonly record struct - 具有值语义的不可变值类型。

直接取自 Microsoft MVP 工程师 İlkay İlknur:

大多数生成的代码看起来类似于记录类。 但是,记录结构和记录类之间存在一个区别。 记录结构中生成的属性默认是可变的。 这个决定背后的原因是与元组一致。 元组就像具有相似特征的匿名记录结构。 另一方面,结构可变性并不像类可变性那样受到关注。 这就是 C# 团队决定让记录结构属性默认可变的原因。 但是,如果您需要不可变的记录结构,则可以使用 readonly 关键字。

记录结构在 csharp

如果您使用位置语法来定义record class ,它的属性是不可变的

record class Point(int X, int Y);

它默认具有{get; init;}的属性附件{get; init;}

如果您以传统方式声明它(没有位置参数),您可以指定您的属性访问器:

record class Point
{
    int X {get; set;}
    int Y {get; set;}
}

您可以混合搭配这两个 styles,但请记住,如果您提供任何位置参数,它们将成为自动实现的构造函数的参数,并且不会设置任何其他属性。

我意识到这实际上并没有回答为什么存在这种行为的问题,我只是希望阅读本文的人不会得出record class是不可变的结论。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM