簡體   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