当前位置: 首页 > news >正文

c#编码技巧(十五):新语法糖record深入分析

c#编码技巧(十四):新语法糖record深入分析

从 C# 9 开始新增了一个关键字record,用于封装数据。
record实质是微软提供的一个语法糖,因很多开源项目都用到了这个关键字,说明这个语法糖比较实用。
那么这个record类型和普通class类型有什么区别呢?我们可以通过工具探究一下源码
首先新建一个普通的类PersonCls,添加两个属性

    /// <summary>/// 普通类/// </summary>public class PersonCls{public string Name { get; set; }public string Address { get; set; }}

再建一个record类型PersonRecord,record类型的声明简洁:一行就搞定,其中属性名字放在括号里,编译器自动为我们生成两个属性

  /// <summary>/// record类型/// </summary>/// <param name="Name"></param>/// <param name="Age"></param>public record PersonRecord(string Name, int Age);//也即public record class PersonRecord(string Name, int Age);//其中class可省略var person = new PersonRecord("Tom", 18);

利用反编译工具查看普通类PersonCls代码,果然非常普通,除了两属性什么都没有

using System;
using System.Runtime.CompilerServices;namespace DotNet6
{// Token: 0x02000005 RID: 5[NullableContext(1)][Nullable(0)]public class PersonCls{// Token: 0x17000001 RID: 1// (get) Token: 0x06000005 RID: 5 RVA: 0x00002092 File Offset: 0x00000292// (set) Token: 0x06000006 RID: 6 RVA: 0x0000209A File Offset: 0x0000029Apublic string Name { get; set; }// Token: 0x17000002 RID: 2// (get) Token: 0x06000007 RID: 7 RVA: 0x000020A3 File Offset: 0x000002A3// (set) Token: 0x06000008 RID: 8 RVA: 0x000020AB File Offset: 0x000002ABpublic string Address { get; set; }}
}

同样利用反编译工具查看PersonRecord,却生成了很多代码
其中

  • 包含一个有参构造函数
  • 生成了两个属性
  • 生成了ToString和运算符比较、Equals比较的方法
  • 还有其他一些方法,方法都很简单暂不做分析
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;namespace DotNet6
{// Token: 0x02000006 RID: 6[NullableContext(1)][Nullable(0)]public class PersonRecord : IEquatable<PersonRecord>{// Token: 0x0600000A RID: 10 RVA: 0x000020BD File Offset: 0x000002BDpublic PersonRecord(string Name, string Address){this.Name = Name;this.Address = Address;base..ctor();}// Token: 0x17000003 RID: 3// (get) Token: 0x0600000B RID: 11 RVA: 0x000020D4 File Offset: 0x000002D4[CompilerGenerated]protected virtual Type EqualityContract{[CompilerGenerated]get{return typeof(PersonRecord);}}// Token: 0x17000004 RID: 4// (get) Token: 0x0600000C RID: 12 RVA: 0x000020E0 File Offset: 0x000002E0// (set) Token: 0x0600000D RID: 13 RVA: 0x000020E8 File Offset: 0x000002E8public string Name { get; set; }// Token: 0x17000005 RID: 5// (get) Token: 0x0600000E RID: 14 RVA: 0x000020F1 File Offset: 0x000002F1// (set) Token: 0x0600000F RID: 15 RVA: 0x000020F9 File Offset: 0x000002F9public string Address { get; set; }// Token: 0x06000010 RID: 16 RVA: 0x00002104 File Offset: 0x00000304[CompilerGenerated]public override string ToString(){StringBuilder stringBuilder = new StringBuilder();stringBuilder.Append("PersonRecord");stringBuilder.Append(" { ");if (this.PrintMembers(stringBuilder)){stringBuilder.Append(' ');}stringBuilder.Append('}');return stringBuilder.ToString();}// Token: 0x06000011 RID: 17 RVA: 0x00002150 File Offset: 0x00000350[CompilerGenerated]protected virtual bool PrintMembers(StringBuilder builder){RuntimeHelpers.EnsureSufficientExecutionStack();builder.Append("Name = ");builder.Append(this.Name);builder.Append(", Address = ");builder.Append(this.Address);return true;}// Token: 0x06000012 RID: 18 RVA: 0x0000218A File Offset: 0x0000038A[NullableContext(2)][CompilerGenerated]public static bool operator !=(PersonRecord left, PersonRecord right){return !(left == right);}// Token: 0x06000013 RID: 19 RVA: 0x00002196 File Offset: 0x00000396[NullableContext(2)][CompilerGenerated]public static bool operator ==(PersonRecord left, PersonRecord right){return left == right || (left != null && left.Equals(right));}// Token: 0x06000014 RID: 20 RVA: 0x000021AC File Offset: 0x000003AC[CompilerGenerated]public override int GetHashCode(){return (EqualityComparer<Type>.Default.GetHashCode(this.EqualityContract) * -1521134295 + EqualityComparer<string>.Default.GetHashCode(this.<Name>k__BackingField)) * -1521134295 + EqualityComparer<string>.Default.GetHashCode(this.<Address>k__BackingField);}// Token: 0x06000015 RID: 21 RVA: 0x000021EC File Offset: 0x000003EC[NullableContext(2)][CompilerGenerated]public override bool Equals(object obj){return this.Equals(obj as PersonRecord);}// Token: 0x06000016 RID: 22 RVA: 0x000021FC File Offset: 0x000003FC[NullableContext(2)][CompilerGenerated]public virtual bool Equals(PersonRecord other){return this == other || (other != null && this.EqualityContract == other.EqualityContract && EqualityComparer<string>.Default.Equals(this.<Name>k__BackingField, other.<Name>k__BackingField) && EqualityComparer<string>.Default.Equals(this.<Address>k__BackingField, other.<Address>k__BackingField));}// Token: 0x06000018 RID: 24 RVA: 0x0000225F File Offset: 0x0000045F[CompilerGenerated]protected PersonRecord(PersonRecord original){this.Name = original.<Name>k__BackingField;this.Address = original.<Address>k__BackingField;}// Token: 0x06000019 RID: 25 RVA: 0x00002280 File Offset: 0x00000480[CompilerGenerated]public void Deconstruct(out string Name, out string Address){Name = this.Name;Address = this.Address;}}
}

使用这些方法,可以看到与普通class类不同的是:

  • record的ToString()可以输出值
  • 属性值相同的两个record类型,使用==或Equals比较,判断为相等
        static async Task Main(string[] args){//record类型ToString()可以输出名称+值,而类只会输出命名空间+类名var clsStr = (new PersonCls() { Name = "LiLei", Address="GD" }.ToString());var str = (new PersonRecord("LiLei", "GD")).ToString();//输出:PersonRecord { Name = LiLei, Address = GD }//属性值相同的普通类,使用==或Equals比较,判断为不相等var cls1 = new PersonCls() { Name = "Tom", Address = "CN" };var cls2 = new PersonCls() { Name = "Tom", Address = "CN" };bool isClassOperatorEquals = cls1 == cls2;//falsebool isClassEquals = cls1.Equals(cls2);//falsebool isClassReferenceEquls = ReferenceEquals(cls1, cls2);//false//属性值相同的两个record类型,使用==或Equals比较,判断为相等;使用ReferenceEquals比较,判断为不相等,因为引用是确实是不同var rcd1 = new PersonRecord("Ben", "HK");var rcd2 = new PersonRecord("Ben", "HK");bool isRecordOperatorEquals = rcd1 == rcd2;// true:因为值相同bool isRecordEquals = rcd1.Equals(rcd2);//true:因为值相同bool isRecordReferenceEquls = ReferenceEquals(rcd1, rcd2);//false:引用不同//rcd1.Address = "shenzhen";//定义在括号内的record的属性值,在new之后不能修改;//想要能修改的属性,就像Level那样声明/*public record PersonRecordCanChange(string Name, string Address){public string Level { get; set; }}*/}

record还有其他用法,比如使用with { }可以复制这个record

            var rcdCopy = rcd1 with { };//复制Console.WriteLine($"name={rcdCopy.Name}, address={rcdCopy.Address}");//name=Ben, address=HK

只想部分复制,可以在{}内更改部分属性的值

            var rcdCopy = rcd1 with { };//复制Console.WriteLine($"name={rcdCopy.Name}, address={rcdCopy.Address}");//name=Ben, address=Beijing

可以继承

    public record Animal(string Head, string Body);public record Human(string Head, string Body, string Hand): Animal(Head, Body);

如果确实需要自定义属性,可以这样写

	public record Points{//声明属性X,Y,并在构造函数中注入赋值public Points(double time, double distance) => (X, Y) = (time, distance);public double X { get; set; }public double Y { get; set; }}var point = new Points(time: 10, distance: 990);var x = point.X;var y = point.Y;

但不建议这样做,这样违背了record的设计初衷

综上所述:

  1. record实质是微软提供的一个语法糖,本质就是一个类,这个类里生成了若干个方法,这些方法就使得record与类区别开来
  2. record的写法简单快捷,可用在数据传输对象中,如dto等,能够大大提升效率,简化代码

相关文章:

c#编码技巧(十五):新语法糖record深入分析

c#编码技巧(十四)&#xff1a;新语法糖record深入分析 从 C# 9 开始新增了一个关键字record&#xff0c;用于封装数据。 record实质是微软提供的一个语法糖&#xff0c;因很多开源项目都用到了这个关键字&#xff0c;说明这个语法糖比较实用。 那么这个record类型和普通class类…...

Java IO流(五)(字符集基础知识简介)

字符集 计算机的存储规则&#xff08;英文字符&#xff09; 常见字符集介绍 a.GB2312字符集&#xff1a;1980年发布&#xff0c;1981年5月1日实施的简体中文汉字编码国家标准。收录7445个图形字符&#xff0c;其中包括6763个简体汉字 b.BIG5字符集&#xff1a;台湾地区繁体中…...

周周爱学习之Redis重点总结

redis重点总结 在正常的业务流程中&#xff0c;用户发送请求&#xff0c;然后到缓存中查询数据。如果缓存中不存在数据的话&#xff0c;就会去数据库查询数据。数据库中有的话&#xff0c;就会更新缓存然后返回数据&#xff0c;数据库中也没有的话就会给用户返回一个空。 1.缓…...

免费的SEO外链发布工具,提升排名的利器

互联网已经成为信息传播和商业发展的重要平台。而对于拥有网站的个人、企业来说&#xff0c;如何让自己的网站在搜索引擎中脱颖而出&#xff1f;SEO&#xff08;Search Engine Optimization&#xff09;作为提高网站在搜索引擎中排名的关键手段. 什么是SEO外链&#xff1f; S…...

腾讯字节常考的linux命令

1 ps 1.1 ps -ef 有哪些字段 ps -ef 命令在Unix/Linux系统中用于显示当前运行的进程。输出的字段通常包括&#xff1a; UID&#xff1a;启动进程的用户ID。PID&#xff1a;进程ID。PPID&#xff1a;父进程ID。C&#xff1a;CPU利用率。STIME&#xff1a;进程启动时间。TTY&a…...

JAVA后端自学技能实操合集

JAVA后端自学技能实操 内容将会持续更新中,有需要添加什么内容可以再评论区留言,大家一起学习FastDFS使用docker安装FastDFS(linux)集成到springboot项目中 内容将会持续更新中,有需要添加什么内容可以再评论区留言,大家一起学习 FastDFS 组名&#xff1a;文件上传后所在的 st…...

C++ 关联容器

关联容器 关联容器支持高效的关键字查找和访问。 两个主要的关联容器&#xff08;associative container&#xff09;类型是 map 和 set。 map 中的元素是一些关键字——值对。 关键字起到索引的作用&#xff0c;值则表示与索引相关联的数据。 set 中的每个元素只包含一个关键…...

ES6之函数新增的扩展

参数 ES6允许为函数的参数设置默认值 function log(x, y World) {console.log(x, y); }console.log(Hello) // Hello World console.log(Hello, China) // Hello China console.log(Hello, ) // Hello函数的形参是默认声明的&#xff0c;不能使用let或const再次声明 functi…...

postgresql安装部署(docker版本)

1.在线部署 创建数据库存储目录 mkdir /home/pgdata创建容器 docker run --name postgresql --restartalways -d -p 5432:5432 -v /home/pgdata:/var/lib/postgresql/data --shm-size10g -e POSTGRES_PASSWORD密码 postgis/postgis:12-3.2-alpine–name为设置容器名称 -d表…...

【Python/Java/C++三种语言】20天拿下华为OD笔试之【位运算】2023B-出错的或电路【欧弟算法】全网注释最详细分类最全的华为OD真题

文章目录 题目描述与示例题目描述输入描述输出描述示例一输入输出说明 示例二输入输出说明 解题思路代码PythonJavaC时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 题目描述与示例 题目描述 某生产门电路的厂商发现某一批次的或门电路不稳定&#xff0c;具体现象为计…...

vscode 编译运行c++ 记录

一、打开文件夹&#xff0c;新建或打开一个cpp文件 二、ctrl shift p 进入 c/c配置 进行 IntelliSense 配置。主要是选择编译器、 c标准&#xff0c; 设置头文件路径等&#xff0c;配置好后会生成 c_cpp_properties.json&#xff1b; 二、编译运行&#xff1a; 1、选中ma…...

错题总结(四)

1.【一维数组】输入10个整数&#xff0c;求平均值 编写一个程序&#xff0c;从用户输入中读取10个整数并存储在一个数组中。然后&#xff0c;计算并输出这些整数的平均值。 int main() {int arr[10];int sum 0;for (int n 0; n < 10; n){scanf("%d", &arr…...

ORACLE使用Mybatis-plus批量插入

ORACLE使用mybatis-plus自带的iservice.saveBatch方法时&#xff0c;会报DML Returing cannot be batch错误&#xff1a; 推测原因是oracle不支持insert into table_name (,) values &#xff08;&#xff0c;&#xff09;,&#xff08;&#xff09;的写法。且oracle不会自动生…...

vue,uniapp的pdf等文件在线预览

vue&#xff0c;uniapp文件在线预览方案&#xff0c;用了个稍微偏门一点的方法实现了 通过后端生成文件查看页面&#xff0c;然后前端只要展示这个网页就行&#xff0c;uniapp就用web-view来展示&#xff0c;后台系统就直接window.open()打开就行 示例查看PDF文件&#xff0c;…...

SpringBoot 项目 Jar 包加密,防止反编译

1场景 最近项目要求部署到其他公司的服务器上&#xff0c;但是又不想将源码泄露出去。要求对正式环境的启动包进行安全性处理&#xff0c;防止客户直接通过反编译工具将代码反编译出来。 2方案 第一种方案使用代码混淆 采用proguard-maven-plugin插件 在单模块中此方案还算简…...

DockerFile中途执行出错的解决办法

DockerFile中途执行出错的解决办法 你们是否也曾经因为DockerFile中途执行出错,而对其束手无策?总是对docker避之不及! 但是当下载的源码运用到了docker,dockerFile 执行到一半,报错了怎么办? 现状 那么当DockerFile执行一半出错后,会产生什么结果呢? 如图可知,生成…...

Word插件-好用的插件-一键设置字体--大珩助手

常用字体 整理了论文、公文常用字体 整理了常用的论文字体&#xff0c;可一键设置当前节或选择的文字的字体 字体设置 包含字体选择、字体颜色 特殊格式 包含首字下沉、段落分栏、统一宽度、双行合一、上标切换、下标切换、转为全角、转为半角、挖词填空、当前日期、大写金…...

【MODBUS】Modbus主站云端服务器和边缘设备部署区别

Modbus主站作为云端服务器&#xff1a; 云端服务器作为主站&#xff1a; 在这种部署方式中&#xff0c;云端服务器充当Modbus通信的主站&#xff0c;负责向不同的Modbus从站发起请求&#xff0c;并处理响应。云端服务器通常与其他云服务一起运行&#xff0c;可以在云平台上实现…...

hbuiler中使用npm安装datav

注&#xff1a;datav边框样式目前使用时&#xff1a;适用于网页&#xff0c;不适用于app 1、先安装node 安装、配置Node路径 2、为Node配置环境变量 3、在hbuilder的设置中填写node的路径 配置 4、打开cmd输入npm install jiaminghi/data-view 安装dataV&#xff0c;&…...

贾佳亚团队新作LLaMA-VID,2token让大模型学会看好莱坞大片

家人们谁懂&#xff0c;连大模型都学会看好莱坞大片了&#xff0c;播放过亿的GTA6预告片大模型还看得津津有味&#xff0c;实在太卷了&#xff01; 而让LLM卷出新境界的办法简单到只有2token——将每一帧编码成2个词即可搞定。等等&#xff01;这种大道至简的方法有种莫名的熟…...

【数据结构】手撕排序

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、排序的概念及其运用1.1 排序的概念1.2 常见的算法排序 二、 冒泡排序三、直接插入排…...

运维05:自动化

人工运维时代 运维人员早期需要维护众多的机器&#xff0c;因此需要执行很多重复的劳动&#xff0c;很多机器需要同时部署相同的服务或者是执行相同的命令&#xff0c;还得反复地登录不同的机器&#xff0c;执行重复的动作 自动化运维时代 早期运维人员会结合ssh免密登录&…...

OpenCL学习笔记(一)开发环境搭建(win10+vs2019)

前言 异构编程开发&#xff0c;在高性能编程中有重要的&#xff0c;笔者本次只简单介绍下&#xff0c;如何搭建简单的开发环境&#xff0c;可以供有需要的小伙伴们开发测试使用 一、获取opencl的sdk库 1.使用cuda库 若本机有Nvidia的显卡&#xff0c;在安装cuda库后&#x…...

寻找两个正序数组的中位数

更好的阅读体验&#xff0c;请点击 YinKai s Blog。 题目&#xff1a;寻找两个正序数组的中位数 给定两个大小分别为 m 和 n 的正序&#xff08;从小到大&#xff09;数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为 O(log (mn)) 。 …...

探索低代码的潜力、挑战与未来展望

低代码开发作为一种新兴的开发方式&#xff0c;正在逐渐改变着传统的编程模式&#xff0c;低代码使得开发者无需编写大量的代码即可快速构建各种应用程序。然而&#xff0c;低代码也引发了一系列争议&#xff0c;有人称赞其为提升效率的利器&#xff0c;也有人担忧其可能带来的…...

unity 2d 入门 飞翔小鸟 小鸟碰撞 及死亡(九)

1、给地面&#xff0c;柱体这种添加2d盒装碰撞器&#xff0c;小鸟移动碰到就不会动了 2、修改小鸟的脚本&#xff08;脚本命名不规范&#xff0c;不要在意&#xff09; using System.Collections; using System.Collections.Generic; using UnityEngine;public class Fly : Mo…...

实时最优控制(Real-Time Optimal Control)工具

系列文章目录 前言 许多现代控制方法&#xff0c;如模型预测控制&#xff08;model-predictive control&#xff09;&#xff0c;在很大程度上依赖于实时解决优化问题。特别是&#xff0c;高效解决优化控制问题的能力使复杂机器人系统在实现高动态行为&#xff08;highly dyna…...

(env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序

应公司需求&#xff0c;在特定情况下需要修改ip 在开发过程中出现的小插曲 1、第一种情况&#xff1a;重复声明 2、第二种情况&#xff1a; 应官方要求&#xff0c;需要跳转的 tabBar 页面的路径&#xff08;需在 pages.json 的 tabBar 字段定义的页面&#xff09;&#xff0…...

go-zero开发入门-API服务开发示例

接口定义 定义 API 接口文件 接口文件 add.api 的内容如下&#xff1a; syntax "v1"info (title: "API 接口文件示例"desc: "演示如何编写 API 接口文件"author: "一见"date: "2023年12月07日"version: "…...

NVIDIA Jetson NX ubuntu20.04删除多余版本冲突的Boost库

参考Ubuntu16.04 卸载旧版本Boost库并安装新版本 卸载 删除/usr/local/include/boost文件夹&#xff0c;删除/usr/local/lib中和boost有关的文件,以及/usr/local/lib/cmake/中boost的cmake文件 cd /usr/local/lib/ ls | grep boost sudo rm -rf /usr/local/include/boost su…...