C# 9 record 并非简单属性 POCO 的语法糖

最近升级专案到大统一 .NET 5 并使用 C#9 语法尝试改写套件,发现之前以为 record 只是简单属性 POCO 的简化语法糖的认知是错误。

另外因为 POCO 属于需定义口语词,这边在本文定义简单属性 POCOpublic class 类别 {public string ID{get;set}/*略*/} 只有属性的简单类别代码

一. rocord 的确底层是 class,但,不是单纯简单属性 POCO class

可以看 IL Spy 反编译程序码,发现系统帮我们做了很多事

二. 预设生成的是属性是 {get;init;} 不是 {get;set;},这代表设定值时间点在 constructor(建构式),延伸产生immutable(不可变)特性,也代表 record 预设为thread-safe(线程安全),因为都是取得一样的值。

所以当你使用 Dapper 类似框架查询完 POCO 资料,想做修改属性时会报 CS8852 无法修改错误。

三. 预设比较逻辑改变

可以看TimCorey写的例子,可以看到预设 class 跟 record 的 == 差异,线上测试连结

public class Program
{
public static void Main()
{
var record1Obj1 = new record1(FirstName: "Lin", LastName: "WeiHan");
var record1Obj2 = new record1(FirstName: "Lin", LastName: "WeiHan");
Console.WriteLine(record1Obj1 == record1Obj2);//true var class1Obj1 = new Class1() { FirstName = "Lin", LastName = "WeiHan" };
var class2Obj2 = new Class1() { FirstName = "Lin", LastName = "WeiHan" };
Console.WriteLine(class1Obj1 == class2Obj2);//false
}
} public record record1(string FirstName,string LastName); public class Class1
{
public string FirstName {get;init;}
public string LastName{get;init;}
}

因为 record override ==Equals,认为只要是同一个 record 类型,并且属性值都一样,系统就会认定为true,也就是俗称的structural equality,可以看 IL Spy 反编译代码

	public virtual bool Equals(record2? other)
{
return (object)other != null && EqualityContract == other!.EqualityContract && EqualityComparer<string>.Default.Equals(FirstName, other!.FirstName) && EqualityComparer<string>.Default.Equals(LastName, other!.LastName);
}

跟 object class 预设会去取得 RuntimeHelpers.GetHashCode Handle 逻辑不相同。

四. GetHashCode也做了类似逻辑,所以属性值一样,HashCode会得到一样的值,线上测试连结



IL Spy 反编译代码

	public override int GetHashCode()
{
return (EqualityComparer<Type>.Default.GetHashCode(EqualityContract) * -1521134295 + EqualityComparer<string>.Default.GetHashCode(FirstName)) * -1521134295 + EqualityComparer<string>.Default.GetHashCode(LastName);
}

五. 注意不能把 record 当作一定是 immutable(不可变),原因在微软没有限制以下写法...

public record record2
{
public string FirstName {get;set;}
public string LastName{get;set;}
}

准许修改 {get;init;}{get;set},将会导致 immutable 跟 thread-safe 特性消失

六. record 会帮忙生成可读性好的 ToString 实作

以下图片为比较一般 class 跟 record 生成的 ToString 差别

七. record 帮忙生成 extend IEquatable<类别> ,并实作强型别public virtual bool Equals(Record1? other)



这代表可以避免原本public override bool Equals(object? obj)需要先 unboxing 再 boxing 的效能损耗问题

阅读资料:

C# 9 record 并非简单属性 POCO 的语法糖的更多相关文章

  1. OC:属性、点语法、KVC

    //属性的属性 属性定义在一个 .h文件里,在这个.h文件里可以定义实例变量(就是这个类的特征),也可以通过   @protery(属性约束关键字) 属性名字类型 属性名 来定义一些属性,在prope ...

  2. C#语法糖之第一篇:自动属性&隐式类型

    今天给大家分享一下C#语法糖的简单的两个知识点吧. 自动属性:在 C# 4.0 和更高版本中,当属性的访问器中不需要其他逻辑时,自动实现的属性可使属性声明更加简洁. 客户端代码还可通过这些属性创建对象 ...

  3. C#在属性中用Lambda语法

    今天看代码改功能的时候遇到了个比较奇怪的地方,在属性里也能用Lambda,我看了好久,也不是很理解,我都开始怀疑这是不是属性了,又在群里讨论了下这个问题,觉得有必要记下来,因为又涨知识了. 问题1:这 ...

  4. iOS语法糖 简单却不那么简单

    转载作者 香蕉大大 (Github) 开发过程中我特别喜欢用语法糖,原因很简单,懒得看到一堆长长的代码,但是语法糖我今天无意中看到更有意思的玩法.这里暂时吧把今天新学到的知识点整理一下希望大家喜欢,如 ...

  5. Python进阶-XVIII 封装、(属性、静态方法、类方法)语法糖、反射

    1.封装 类中的私有化:属性的私有化和方法的私有化 会用到私有的这个概念de场景 1.隐藏起一个属性 不想让类的外部调用 2.我想保护这个属性,不想让属性随意被改变 3.我想保护这个属性,不被子类继承 ...

  6. ES6 class 语法糖不能直接定义原型上的属性

    今天注意到两个东西: 1.为了模拟面向对象,JavaScript的class语法糖屏蔽了原型的概念 class A{ a = 1   // 注意!!这里定义的不是在prototype上的属性,而是给实 ...

  7. 4.简单的 GNU 汇编语法

    芯片启动时很多设备没有初始化,需要汇编语言进行准备. 简单的GNU汇编语法: 1 label: instruction @ comment label :标号,类似于外号,为所在位置做标号,可以通过这 ...

  8. salesforce 零基础学习(二十九)Record Types简单介绍

    在项目中我们可能会遇见这种情况,不同的Profile拥有不同的页面,页面中的PickList标签可能显示不同的值.这个时候,使用Record Types可以很便捷的搞定需求. Record Types ...

  9. EF框架step by step(5)—处理实体简单属性

    EF框架会对实体进行跟踪,对实体的每个属性当前值和原始值及其状态进行跟踪,记录.当前值是指实体属性当前的被赋予的值,而原始值是指实体最初从数据库读取或者附加到DbContext时的值. 先通过简单的代 ...

随机推荐

  1. SQL 使用openquery进行跨库操作

    摘自:http://www.cnblogs.com/aji88/archive/2009/11/06/1597263.html 对给定的链接服务器执行指定的传递查询.该服务器是 OLE DB 数据源. ...

  2. 一键开启win10全局utf8,编码问题说拜拜

    在windows下开发,开发环境的配置是一个很头大的问题,而编码问题是另一个令人头大的问题,常常出现的中文乱码令人痛不欲生,其原因就在于windows默认的编码并不是现在很普遍的utf8格式,本文就来 ...

  3. Linux系统部署WEB项目(2020最新最详细)

    2020最新Linux系统发行版ContOS7演示部署WEB项目 为防止操作权限不足,建议切换root用户,当然如果你对Linux命令熟悉,能够自主完成权限更新操作,可以不考虑此推荐. 更多命令学习推 ...

  4. Spring之AOP(面向切面编程)_入门Demo

    AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可 ...

  5. java面试题目之JVM(YW制作仅供参考)

    1.JVM工作原理 2.JVM组成部分及其作用. java虚拟机分为两个子系统和两个组件. 两个子系统分别是类加载器和执行引擎,类加载器负责加载字节码(.class)文件到JVM的内存中,执行引擎负责 ...

  6. JVM内存管理和垃圾回收

    无论对于Java程序员还是大数据研发人员,JVM是必须掌握的技能之一.既是面试中经常问的问题,也是在实际业务中对程序进行调优.排查类似于内存溢出.栈溢出.内存泄漏等问题的关键.笔者将按下图分多篇文章详 ...

  7. php反序列化漏洞入门

    前言 这篇讲反序列化,可能不会很高深,我之前就被反序列化整懵逼了. 直到现在我对反序列化还是不够深入,今天就刚好可以研究研究. 0x01.反序列化漏洞介绍 序列化在内部没有漏洞,漏洞产生是应该程序在处 ...

  8. 【总结】vertica数据库

    1.简介 Vertica是一款基于列式存储架构的数据库,可以支持存放多至PB级别的结构化数据 2.列式存储 行式存储就是以行为单位进行存储,再配合B+树作为索引,就能快速通过主键找到相应的行数据.即大 ...

  9. Some problems in openMP's parallel for

    Overview Somehow I started preparing for the ASC competition.When I'm trying my second demo pi, whic ...

  10. 框架篇:见识一下linux高性能网络IO+Reactor模型

    前言 网络I/O,可以理解为网络上的数据流.通常我们会基于socket与远端建立一条TCP或者UDP通道,然后进行读写.单个socket时,使用一个线程即可高效处理:然而如果是10K个socket连接 ...