您的位置:首页 > 其它

浅析 record 使用场景

2021-01-30 00:31 761 查看

浅析 record 使用场景

Intro

之前我们有介绍过

record
基本知识,
record
会实现基于值的类型比较,最近遇到的几个问题觉得用
record
来解决会非常方便,分享一下

基于值的类型比较

最近有遇到一个场景,需要比较两个 JSON 字符串是否相等,字符串比较简单,就是一个固定值的

Dictionary
,或者认为它就是一个简单的
Model
,但是 JSON 字符串的的属性顺序可能不同,比如说下面的这个示例:

{"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 有收到反馈说,调用多次返回的结果不同,于是我就想写一段代码调用个一百次看是否会有重复,大致代码如下:

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
来实现

之前我实现了一个简单的日志框架,有一个日志对象,定义如下:

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 { g
56c
et; 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 {
56c
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;
}
}

More

record
在很多场景下能够简化我们的代码,使得代码更加干净简洁,在合适的场景下不要忘记使用哦~

微软的反向代理项目 YARP 也使用了

record
来简化原来代码中
DeepClone
的功能,可以参考 PR:https://github.com/microsoft/reverse-proxy/pull/662

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: