以前咱们有介绍过 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