C# 9 引入record,它一种可以创建的新引用类型,而不是类或结构。 C# 10 添加了 record structs,以便可以将记录定义为值类型。 记录与类不同,区别在于record类型使用基于值的相等性。 两个记录类型的变量在它们的类型和值都相同时,它们是相等的。with 表达式在 C# 9.0 及更高版本中可用,使用修改的特定属性和字段生成其操作数的副本。以下介绍C# 9.0 record和with的定义及使用。
1、record定义及使用
record
类型的实际是一个引用类型 ,但具备值类型的行为。重写了Equals
等对象类型的比较方法,在两个不同引用的record
对象的内容相同时,对两者进行==
比较,判断两者相等为true
。重写了ToString()
方法,便于输出属性内容。还重写了GetHashCode()
和Equals()
方法。
1)定义record类型
public record Language { public string LastName { get; } public string FirstName { get; } public Language(string first,string last) => (FirstName,LastName) = (first,last); }
创建使用:
Language lang = new("JavaScript","JS");//Language lang = new Language("JavaScript","JS");
用对象初始化器进行初始化,则在属性中使用init关键字,
如下,
public record Language { public string? FirstName { get; init; } public string? LastName { get; init; } }
创建使用:
Language lang = new(){ FirstName = "JavaScript",LastName = "JS"};//Language lang = new(){ FirstName = "JavaScript",LastName = "JS"}
注意:由于有set
访问器,所以它支持用对象初始化器进行初始化,如想用构造函数进行初始化,可以添加自己的构造函数。 init 就是自动生成了一个对 私有只读字段 的封装,多了一种让你初始化 只读字段 的方式。
上面定义是不可变类型record
,定义可变类型rcord
代码,如下,
public record Language { public string? FirstName { get; set; } public string? LastName { get; set; } }
2)解构函数
将record
对象能解构成元组,需要为record
添加解构函数Deconstruct
。通过构造函数的参数传入,并通过位置解构函数提取出来。
例如,
public record Language { public string FirstName { get; init; } public string LastName { get; init; } public Language(string firstName,string lastName) => (FirstName,LastName) = (firstName,lastName); public void Deconstruct(out string firstName,out string lastName) => (firstName,lastName) = (FirstName,LastName); }
使用:
var language = new Language("JavaScript","JS"); // 位置构造函数 var (firstName,lastName) = person; // 位置解构函数
3)定义protected属性
可以使用更简单的方式,代码如下,
public record Language(string firstName,string lastName) { protected string FirstName { get; init; } = firstName; protected string LastName { get; init; } = lastName; }
4)record的面向对象
在面向对象方面,支持继承,多态等所有特性。record
的基类也是object
。record
只能从记录继承,record
不能定义为static
的,但是可以有static
成员。不能从类继承调用父类构造函数可以使用方式如下,
public record Student(string firstName,string lastName,int ID) : Language(firstName,lastName);
2、with的使用
with
表达式,用于拷贝原有对象,并对特定属性进行修改。在 C# 9.0 中,with
表达式的左侧操作数必须为with
。 从 C# 10 开始,with 表达式的左侧操作数也可以为with
或匿名类型。
例如,
using System; public class InheritanceExample { public record Point(int X,int Y); public record NamedPoint(string Name,int X,int Y) : Point(X,Y); public static void Main() { Point p1 = new NamedPoint("A",0); Point p2 = p1 with { X = 5,Y = 3 }; Console.WriteLine(p2 is NamedPoint); // output: True Console.WriteLine(p2); // output: NamedPoint { X = 5,Y = 3,Name = A } } }
对于引用类型成员,在复制操作数时仅复制对成员实例的引用。 副本和原始操作数都具有对同一引用类型实例的访问权限。
例如,
using System; using System.Collections.Generic; public class ExampleWithReferenceType { public record TaggedNumber(int Number,List<string> Tags) { public string PrintTags() => string.Join(",",Tags); } public static void Main() { var original = new TaggedNumber(1,new List<string> { "A","B" }); var copy = original with { Number = 2 }; Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}"); // output: Tags of copy: A,B original.Tags.Add("C"); Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}"); // output: Tags of copy: A,B,C } }
原文地址:https://blog.csdn.net/lwf3115841/article/details/134272297
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。