【问题标题】:C# - Why are record classes immutable by default, but record structs are not?C# - 为什么默认情况下记录类是不可变的,但记录结构不是?
【发布时间】:2022-11-26 15:18:45
【问题描述】:

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

使用记录类...

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-不变的具有值语义的值类型。

【问题讨论】:

    标签: c# record


    【解决方案1】:

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

    大多数生成的代码看起来与记录类相似。 但是,记录结构和记录之间有一个区别 类。记录结构中生成的属性是可变的 默认。这个决定背后的原因是为了与 元组。元组就像具有类似的匿名记录结构 特征。另一方面,结构可变性不具有相同的 类可变性的关注程度。这就是 C# 团队的原因 决定默认使记录结构属性可变。然而, 如果你需要不可变的记录结构,你可以使用 readonly 关键词。

    record-structs-in-csharp

    【讨论】:

      【解决方案2】:

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

      record class Point(int X, int Y);
      

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

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-02
        • 1970-01-01
        • 2013-05-26
        • 2016-04-22
        • 1970-01-01
        相关资源
        最近更新 更多