以前咱們有介紹過 record
基本知識,record
會實現基於值的類型比較,最近遇到的幾個問題以爲用 record
來解決會很是方便,分享一下git
最近有遇到一個場景,須要比較兩個 JSON 字符串是否相等,字符串比較簡單,就是一個固定值的 Dictionary
,或者認爲它就是一個簡單的 Model
,可是 JSON 字符串的的屬性順序可能不一樣,好比說下面的這個示例:github
{"Id":1, "Name":"Tom"}
, {"Name":"Tom", "Id":1}
,這兩個字符串從字符串上來講順序不一樣,天然不相等,可是對應的屬性的值是相同的,怎麼比較方便的進行比較呢,使用 record
能夠比較方便進行比較,來看代碼:框架
record Person(int Id, string Name); [Fact] public void RecordTest() { var str1 = "{\"Id\":1, \"Name\":\"Tom\"}"; var p1 = JsonConvert.DeserializeObject<Person>(str1); var str2 = "{\"Name\":\"Tom\",\"Id\":1}"; var p2 = JsonConvert.DeserializeObject<Person>(str2); Assert.True(p1 == p2); Assert.Equal(p1, p2); }
咱們有一個 API 有收到反饋說,調用屢次返回的結果不一樣,因而我就想寫一段代碼調用個一百次看是否會有重複,大體代碼以下:this
public record Result { public string Data { get; set;} public int Code { get; set; } } var i = 100; var results = new HashSet<Result>(); using var httpClient = new HttpClient(); while(i-- > 0) { var responseText = await httpClient.GetStringAsync(""); var result = JsonConvert.DeserializeObject<Result>(responseText); results.Add(result); } Console.WriteLine(results.Count);
由於 record
不只會重寫 Equals
方法還會重寫 GetHashCode
方法,因此可使用 HashSet
或者 Dictionary
來實現去重代理
record
提供了 with
表達式來方便的克隆一個新的對象,因此在須要克隆的時候能夠考慮使用 record
,另外全部原型模式的地方均可以考慮使用 record
來實現日誌
以前我實現了一個簡單的日誌框架,有一個日誌對象,定義以下:code
public class LogHelperLoggingEvent : ICloneable { public string CategoryName { get; set; } public DateTimeOffset DateTime { get; set; } public string MessageTemplate { get; set; } public string Message { get; set; } public LogHelperLogLevel LogLevel { get; set; } public Dictionary<string, object> Properties { get; set; } public LogHelperLoggingEvent Copy() { var newEvent = new LogHelperLoggingEvent() { CategoryName = CategoryName, DateTime = DateTime, MessageTemplate = MessageTemplate, Message = Message, LogLevel = LogLevel }; if (Properties != null) { newEvent.Properties = new Dictionary<string, object>(); foreach (var property in Properties) { newEvent.Properties[property.Key] = property.Value; } } return newEvent; } }
咱們可使用 MemberwiseClone
作一個簡化對象
public class LogHelperLoggingEvent : ICloneable { public string CategoryName { get; set; } public DateTimeOffset DateTime { get; set; } public string MessageTemplate { get; set; } public string Message { get; set; } public LogHelperLogLevel LogLevel { get; set; } public Dictionary<string, object> Properties { get; set; } public LogHelperLoggingEvent Copy() { var newEvent = (LogHelperLoggingEvent)MemberwiseClone(); if (Properties != null) { newEvent.Properties = new Dictionary<string, object>(); foreach (var property in Properties) { newEvent.Properties[property.Key] = property.Value; } } return newEvent; } }
使用了 record
以後以下,with
表達式返回的是強類型的對象,再也不須要本身作強制類型轉換了,上面的作法仍是比較取巧的辦法,使用了 MemberwiseClone
去作複製,若是本身寫代碼一個一個複製,將會更加繁瑣,使用 record
以後就很簡單了,只是咱們須要注意一下,with
表達式也只是淺複製,若是內部包含複雜引用類型,須要當心使用字符串
public record LogHelperLoggingEvent { public string CategoryName { get; set; } public DateTimeOffset DateTime { get; set; } public string MessageTemplate { get; set; } public string Message { get; set; } public LogHelperLogLevel LogLevel { get; set; } public Dictionary<string, object> Properties { get; set; } public LogHelperLoggingEvent Copy() { var newEvent = this with{ }; if (Properties != null) { newEvent.Properties = new Dictionary<string, object>(); foreach (var property in Properties) { newEvent.Properties[property.Key] = property.Value; } } return newEvent; } }
record
在不少場景下可以簡化咱們的代碼,使得代碼更加乾淨簡潔,在合適的場景下不要忘記使用哦~get
微軟的反向代理項目 YARP 也使用了 record
來簡化原來代碼中 DeepClone
的功能,能夠參考 PR:https://github.com/microsoft/reverse-proxy/pull/662