class 示範
在 C# 中,我們可以使用 class 關鍵字來自訂物件,例如定義具有 Id 和 Name 兩個屬性的 User 類別:
public class User
{
public int Id;
public string Name;
}
實例化物件:
var user = new User()
{
Id = 1,
Name = "小明",
};
record 示範
除了 class 外,我們也可以使用 record 關鍵字來定義一個以值為基礎的類型
public record User(int Id, string Name);
實例化物件:
var user = new User(1, "小明");
在上面的定義中,User 的屬性是不可以變更(Immutability)的,因為在預設宣告時已經自動加入 init-only 屬性,如果想要改變就會拋出例外:
var user = new User(1, "小明");
user.Id = 2;
// Init-only property 'User. Id' can only be assigned in an object initializer, or on 'this' or 'base' in an instance constructor or an 'init' accessor
讓 record 屬性值可以被更新
上面說 record 的屬性值不可以更新,但是這不是絕對的,而是指預設情況,還是有方法能夠讓 record 被改變:
// 定義可以被改變值的 record 類型
public record User
{
public int Id { get; set; }
public string Name { get; set; }
}
// 實例化
var user = new User()
{
Id = 1,
Name = "小明",
};
// 可以改變值而不會遇到錯誤
user.Id = 2;
針對屬性顯示最佳化的 ToString 方法
平時將資料印出時會自動呼叫 ToString 方法,平時直接執行類別的 ToString 方法會回傳 物件的命名空間和類別名稱:
var user = new User()
{
Id = 1,
Name = "小明",
};
Console.WriteLine(user.ToString());
// ConsoleAppRecordTest0824.Program+User
而針對 record,ToString 方法會使用以下格式回傳: 類型名稱 { 屬性 = 值, 屬性 = 值 }
// public record User(int Id, string Name);
var user = new User(1, "小明");
Console.WriteLine(user.ToString());
// User { Id = 1, Name = 小明 }
物件比較
對於 class 的比較,會比較兩者的記憶體位置是否相等,而對於 record 則會比較兩者的類型和值,只要內容一樣就會回傳 True
var user1 = new User(1, "小明");
var user2 = new User(1, "小明");
Console.WriteLine(user1 == user2); // True
在上面的範例中 User 是 record ,如果是 class 則會是 False
解構賦值
相比於 class,record 還有一個很棒的地方,可以使用元組(Tuple)的解構賦值方式來將 record 的資料取出,但是僅限於使用括號宣告的類型:
// public record User(int Id, string Name);
var user = new User(1, "小明");
var (id, name) = user;
Console.WriteLine($"id: {id}, name: {name}");
// id: 1, name: 小明
參考資料:
Microsoft.Learn - Records (C# reference)
Microsoft.Learn - Create record types
Microsoft.Learn - Deconstructing tuples and other types
感謝教學~
回覆刪除