如何在 C# 9 中使用record类型?
原文鏈接:https://www.infoworld.com/article/3607372/how-to-work-with-record-types-in-csharp-9.html
原文標題:How to work with record types in C# 9
翻譯:沙漠盡頭的狼(谷歌翻譯加持)
利用 C# 9 中的record類型來構建不可變類型和線程安全對象。
不可變性使您的對象線程安全并有助于改進內存管理。它還使您的代碼更具可讀性和更易于維護。不可變對象被定義為一旦創建就無法更改的對象。因此,不可變對象本質上是線程安全的,并且不受競爭條件的影響。
直到最近,C# 還不支持開箱即用的不可變性。C# 9 通過新的 init-only 屬性和record類型引入了對不可變性的支持。僅init-only屬性可用于使對象的各個屬性不可變,而record可用于使整個對象不可變。
因為不可變對象不會改變它們的狀態,所以在多線程和數據傳輸對象等許多用例中,不可變性是一個理想的特性。本文討論了我們如何在 C# 9 中使用 init-only 屬性和record類型。
要使用本文中提供的代碼示例,您應該在系統中安裝 Visual Studio 2019。如果您還沒有安裝,可以在此處下載 Visual Studio 2019[1]。
在 Visual Studio 中創建控制臺應用程序項目
首先,讓我們在 Visual Studio 中創建一個 .NET Core 控制臺應用程序項目。假設您的系統中安裝了 Visual Studio 2019,請按照下面概述的步驟在 Visual Studio 中創建一個新的 .NET Core 控制臺應用程序項目。
啟動 Visual Studio IDE。
單擊“Create new project.”。
在“Create new project”窗口中,從顯示的模板列表中選擇“Console App (.NET Core)”。
點擊下一步。
在接下來顯示的“Configure your new project”窗口中,指定新項目的名稱和位置。
單擊創建。
遵循這些步驟將在 Visual Studio 2019 中創建一個新的 .NET Core 控制臺應用程序項目。我們將在本文的后續部分中使用該項目。
在 C# 9 中使用 init-only 屬性
init-only屬性是那些只能在對象初始化時賦值的屬性。請參閱以下包含 init-only 屬性的類。
public?class?DbMetadata {public?string?DbName?{?get;?init;?}public?string?DbType?{?get;?init;?} }您可以使用以下代碼片段創建 DbMetadata 類的實例并初始化其屬性。
DbMetadata?dbMetadata?=?new?DbMetadata() {DbName?=?"Test",DbType?=?"Oracle" };請注意,對 init-only 字段的后續分配是非法的。因此,以下語句將無法編譯。
dbMetadata.DbType?=?"SQL?Server";在 C# 9 中使用record類型
C# 9 中的record類型是僅具有只讀屬性的輕量級、不可變數據類型(或輕量級類)。因為record類型是不可變的,所以它是線程安全的,并且在創建后不能改變或更改。您只能在構造函數中初始化record類型。
您可以使用 record 關鍵字聲明record,如下面的代碼片段所示。
public?record?Person {public?string?FirstName?{?get;?set;?}public?string?LastName?{?get;?set;?}public?string?Address?{?get;?set;?}public?string?City?{?get;?set;?}public?string?Country?{?get;?set;?} }請注意,僅將類型標記為record(如前面的代碼片段所示)本身不會為您提供不可變性。要為您的record類型提供不可變性,您必須使用 init 屬性,如下面的代碼片段所示。
public?record?Person {public?string?FirstName?{?get;?init;?}public?string?LastName?{?get;?init;?}public?string?Address?{?get;?init;?}public?string?City?{?get;?init;?}public?string?Country?{?get;?init;?} }您可以使用以下代碼片段創建 Person 類的實例并初始化其屬性。
var?person?=?new?Person {FirstName?=?"Joydip",LastName?=?"Kanjilal",Address?=?"192/79?Stafford?Hills",City?=?"Hyderabad",Country?=?"India" };在 C# 9 中使用 with 表達式
如果某些屬性具有相同的值,您可能經常希望從另一個對象創建一個對象。但是,記錄類型的 init-only 屬性會阻止這種情況。例如,以下代碼片段將無法編譯,因為默認情況下名為 Person 的record類型的所有屬性都是 init-only。
var?newPerson?=?person; newPerson.Address?=?"112?Stafford?Hills"; newPerson.City?=?"Bangalore";幸運的是,有一個解決方法——with 關鍵字。通過指定屬性值的更改,您可以利用 with 關鍵字從另一個record類型創建一個實例。以下代碼片段說明了如何實現這一點。
var?newPerson?=?person?with{?Address?=?"112?Stafford?Hills",?City?=?"Bangalore"?};C# 9 中record類型的繼承
record類型支持繼承。也就是說,您可以從現有record類型創建新record類型并添加新屬性。以下代碼片段說明了如何通過擴展現有record類型來創建新record類型。
public?record?Employee?:?Person {public?int?Id?{?get;?init;?}public?double?Salary?{?get;?init;?} }C# 9 中的位置record
默認情況下,使用位置參數創建的record類型實例是不可變的。換句話說,您可以通過使用構造函數參數傳遞有序的參數列表來創建record類型的不可變實例,如下面給出的代碼片段所示。
var?person?=?new?Person("Joydip",?"Kanjilal",?"192/79?Stafford?Hills",?"Hyderabad",?"India");在 C# 9 中檢查record實例是否相等
在 C# 中檢查類的兩個實例是否相等時,比較基于這些對象的引用(身份)。但是,如果您檢查record類型的兩個實例是否相等,則比較基于record類型的實例中的值。
以下代碼片段說明了一個名為 DbMetadata 的record類型,它由兩個字符串屬性組成。
public?record?DbMetadata {public?string?DbName?{?get;?init;?}public?string?DbType?{?get;?init;?} }以下代碼片段顯示了如何創建 DbMetadata 記錄類型的兩個實例。
DbMetadata?dbMetadata1?=?new?DbMetadata() {DbName?=?"Test",DbType?=?"Oracle" }; DbMetadata?dbMetadata2?=?new?DbMetadata() {DbName?=?"Test",DbType?=?"SQL?Server" };您可以使用 Equals 方法檢查相等性。以下兩個語句將在控制臺窗口中顯示“false”。
Console.WriteLine(dbMetadata1.Equals(dbMetadata2)); Console.WriteLine(dbMetadata2.Equals(dbMetadata1));考慮以下創建 DbMetadata record類型的第三個實例的代碼片段。請注意,實例 dbMetadata1 和 dbMetadata3 包含相同的值。
DbMetadata?dbMetadata3?=?new?DbMetadata() {DbName?=?"Test",DbType?=?"Oracle" };以下兩條語句將在控制臺窗口中顯示“true”。
Console.WriteLine(dbMetadata1.Equals(dbMetadata3)); Console.WriteLine(dbMetadata3.Equals(dbMetadata1));盡管record類型是引用類型,但 C# 9 提供了合成方法來遵循基于值的相等語義。編譯器為您的record類型生成以下方法以強制實施基于值的語義:
Object.Equals(Object) 方法的重載
接受record類型作為其參數的虛擬 Equals 方法
Object.GetHashCode() 方法的重載
兩個相等運算符的方法,即 == 運算符 和 != 運算符
record類型實現 System.IEquatable<T>
此外,記錄類型提供了 Object.ToString() 方法的重載。這些方法是隱式生成的,您無需重新實現它們。
檢查 C# 中的 Equals 方法
您可以檢查是否已隱式生成了 Equals 方法。為此,請在 DbMetadata 記錄中添加一個 Equals 方法,如下所示。
public?record?DbMetadata {public?string?DbName?{?get;?init;?}public?string?DbType?{?get;?init;?}public?override?bool?Equals(object?obj)?=>obj?is?DbMetadata?dbMetadata?&&?Equals(dbMetadata); }當您編譯代碼時,編譯器將用以下消息標記錯誤:
Type 'DbMetadata' already defines a member called 'Equals' with the same parameter types
盡管record類型是一個類,但 record 關鍵字提供了額外的類似值類型的行為和語義,使record與類不同。record本身是一種引用類型,但它使用自己的內置相等性檢查——相等性是通過值而不是引用來檢查的。最后,請注意record可以是可變的,但它們主要是為不變性而設計的。
參考資料
[1]
Visual Studio 2019: https://visualstudio.microsoft.com/downloads/
總結
以上是生活随笔為你收集整理的如何在 C# 9 中使用record类型?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 你也可以搞懂的微服务第一篇——来自Tho
- 下一篇: 微软面向初学者的机器学习课程:1.4-机