c#发展

首页 » 常识 » 预防 » C90中的Records
TUhjnbcbe - 2020/11/30 10:03:00

在C#中的数据类型主要分为引用类型和值类型。

C#9.0中引入了记录(record)类型,它是一种特殊的引用类型,它提供合成方法来提供值类型相等性的语义。也就是说,使用record类型可以创建出不可变的引用类型,但是有类似于值类型的行为。譬如可以使用基于值相等性的比较方法,相同值的实例有相同的HashCode。

声明一个结构用struct关键字,声明一个类用class关键字,C#9.0中引入了一个新的关键字record,使用record关键字来声明一个不可变类型。

不可变类型可以理解为:一旦对象实例化或初始化,不变类型就永远不会改变。不可变的类型只有一种状态,就是在创建对象时指定的状态。

定义一个record类型:

publicrecordDemo{publicstringName1{get;set;}publicstringName2{get;init;}}

注:如果不了解init关键字,请参考C#9.0中的Init-Only属性。

与class一样,record也有一些类的特性,譬如:

record支持继承

可以使用abstract、sealed等修饰符

下面做个非常简单的研究。

定义一个Person的class:

publicclassPerson{publicstringFirstName{get;init;}publicstringLastName{get;init;}}

实例化两个Person对象,并进行对比:

Personperson1=newPerson{FirstName="San",LastName="Zhang"};Personperson2=newPerson{FirstName="San",LastName="Zhang"};Console.WriteLine(person1.GetHashCode());Console.WriteLine(person2.GetHashCode());Console.WriteLine(person1==person2);Console.WriteLine(person1.Equals(person2));

虽然person1和person2都是Person的实例,但是由于是引用类型,在两次实例化之后,两个实例在内存空间中就分配了不一样的地址,所以在不重写Equals方法或运算符重载的情况下,直接对比两个实例,结果肯定是不相等的。

简单看一下运行后的输出结果:

dotnetrunFalseFalse

将Person改成record:

publicrecordPerson{publicstringFirstName{get;init;}publicstringLastName{get;init;}}

实例化两个Person对象:

Personperson1=newPerson{FirstName="San",LastName="Zhang"};Personperson2=newPerson{FirstName="San",LastName="Zhang"};Console.WriteLine(person1.GetHashCode());Console.WriteLine(person2.GetHashCode());Console.WriteLine(person1==person2);Console.WriteLine(person1.Equals(person2));

简单看一下运行后的输出结果:

dotnetrunTrueTrue

可以看出,两个record类型的实例在属性的值相等的情况下,HashCode和对比运算的计算结果都是相同的,具有类似于值类型相同的行为。

那什么情况下使用record类型或使用record有什么好处呢?

record类型在使用消息传递时和在大型的分布式体系结构中非常有用。当对象是不可变类型时候,我们不必担心应用程序的其他部分会对其进行修改。

record类型可以减少某些情况下使用lock的需要,并简化了系统中所有高度并发的部分。

record类型是线程安全的,不需要修改也不需要进行状态同步,同时没有占用修改对象的线程,所以可以自由的共享。

record类型的最大好处是减少了所需的内存分配,由于不可变,所以除了原始记录分配之外,不需要其他内存分配。

注意:

如果定义的record和class类型的属性都是init的时候,虽然都可以实现不可变类型,但是通过合成方法,record类型会有值类型相等的语义。

全栈哥

点开,斐波那契!

1
查看完整版本: C90中的Records