简体   繁体   English

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

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

I was taught that structs should almost always be immutable, so this unusual behaviour of record classes vs. record structs threw me off guard.我被告知结构应该几乎总是不可变的,所以记录类与记录结构的这种不寻常行为让我措手不及。

Using a record class...使用一条记录class...

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

Using a record struct...使用记录结构...

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

Using a readonly record struct...使用只读记录结构...

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

Why are non readonly record structs mutable by default, and why doesn't the same behaviour apply for record classes?为什么readonly记录结构在默认情况下是可变的,为什么相同的行为不适用于记录类?

Edit: I guess what I'm asking here is, why is the syntax... weird?编辑:我想我在这里问的是,为什么语法......很奇怪?

For example, it would seem more logical like:例如,它看起来更符合逻辑:

  • record class - mutable reference type with value semantics. record class - 具有值语义的可变引用类型。
  • readonly record class - immutable reference type with value semantics. readonly record class - 具有值语义的不可变引用类型。
  • record struct - mutable value type with value semantics. record struct - 具有值语义的可变值类型。
  • readonly record struct - immutable value type with value semantics. readonly record struct - 具有值语义的不可变值类型。

Taken directly from a Microsoft MVP Engineer İlkay İlknur:直接取自 Microsoft MVP 工程师 İlkay İlknur:

Most of the generated code looks similar to the record classes.大多数生成的代码看起来类似于记录类。 However, there is one difference between record structs and record classes.但是,记录结构和记录类之间存在一个区别。 The generated properties in record structs are mutable by default.记录结构中生成的属性默认是可变的。 The reason behind this decision was to be consistent with tuples.这个决定背后的原因是与元组一致。 Tuples are like anonymous record structs with similar features.元组就像具有相似特征的匿名记录结构。 On the other hand, struct mutability does not carry the same level of concern as class mutability does.另一方面,结构可变性并不像类可变性那样受到关注。 That's why the C# team decided to make record struct properties mutable by default.这就是 C# 团队决定让记录结构属性默认可变的原因。 However, if you need immutable record structs, you can use the readonly keyword.但是,如果您需要不可变的记录结构,则可以使用 readonly 关键字。

record-structs-in-csharp 记录结构在 csharp

If you use the positional syntax for defining a record class , it's properties are immutable如果您使用位置语法来定义record class ,它的属性是不可变的

record class Point(int X, int Y);

It defaults to having property accessory of {get; init;}它默认具有{get; init;}的属性附件{get; init;}

If you declare this in a traditional way (without positional parameters), you can specify your property accessors:如果您以传统方式声明它(没有位置参数),您可以指定您的属性访问器:

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

You can mix and match these two styles, but bear in mind that if you provide any positional parameters, they will become the parameters on the auto implemented constructor, and any other properties will not be set.您可以混合搭配这两个 styles,但请记住,如果您提供任何位置参数,它们将成为自动实现的构造函数的参数,并且不会设置任何其他属性。

I realise this doesn't actually answer the question as to why this behaviour exists, I'm just hoping that people that read this won't come away with the conclusion that record class is immutable.我意识到这实际上并没有回答为什么存在这种行为的问题,我只是希望阅读本文的人不会得出record class是不可变的结论。

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

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