【C#/.NET】record介绍

这篇具有很好参考价值的文章主要介绍了【C#/.NET】record介绍。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 目录

 

什么是record?

使用record

record解构

record原理

结论


 

什么是record?

record是.NET 5中的一种新特性,可以看作是一种概念上不可变的类。records可以帮助我们在C#中更容易地处理数据,同时提供了重要的功能,如对象相等性、hashcode和解构。

与类不同,records具有值语义。也就是说,当比较两个records的实例时,比较的是这些实例的属性而非引用。这意味着,如果两个records的属性值相同,它们就是相等的。

record也可以简化需要类似于Dto的数据结构容器的定义。

使用record

Person p1 = new("小明", "南山", "11@outlook.com");
Person p2 = new("小明", "南山", "11@outlook.com");

Console.WriteLine(p1 == p2);
public record Person(string Name, string Address, string Email);
【C#/.NET】record介绍

像定义一个类一样,public class Person,只是将class关键字替换成record关键字。然后属性是用括号来定义。

默认的record声明是class,如果想声明一个struct

public record struct Person(string Name, string Address, string Email);

 

【C#/.NET】record介绍

record是不可变的类型,括号中声明的属性在构造之后不可变更。可以使用==按属性的值进行比较。可以直接作为hash的key以及结构。

record可以像普通类一样扩展可变更的属性和自定义的方法,语法如下

public record Person(string Name, string Address, string Email)
{
    public required string PhoneNumber { get; set; }
    public static IEnumerable<Person> GetAll()
    {
        yield return new Person("张三", "123 Main St", "john@example.com") { PhoneNumber = "123456789"};
        yield return new Person("李四", "456 Elm St", "jane@example.com") { PhoneNumber = "123456789" };
        yield return new Person("王二", "789 Oak St", "bob@example.com") { PhoneNumber = "123456789" }; ;
    }

    public string GetDisplayName() => $"{Name} ({Email})";
};

 

【C#/.NET】record介绍

record解构

record可以通过解构,将对象解构为元组,方便一次性获取record中的属性值,

Person p1 = new("小明", "南山", "11@outlook.com") ;

var (name,address,email) = p1 ;

 

【C#/.NET】record介绍

record原理

record的原理是编译器提供支持,上述Person定义反编译结果如下

public class Person : IEquatable<Person>
{
    [CompilerGenerated]
    protected virtual Type EqualityContract
    {
        [CompilerGenerated]
        get
        {
            return typeof(Person);
        }
    }

    public string Name { get; set/*init*/; }

    public string Address { get; set/*init*/; }

    public string Email { get; set/*init*/; }

    public Person(string Name, string Address, string Email)
    {
        this.Name = Name;
        this.Address = Address;
        this.Email = Email;
        base..ctor();
    }

    [CompilerGenerated]
    public override string ToString()
    {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.Append("Person");
        stringBuilder.Append(" { ");
        if (PrintMembers(stringBuilder))
        {
            stringBuilder.Append(' ');
        }
        stringBuilder.Append('}');
        return stringBuilder.ToString();
    }

    [CompilerGenerated]
    protected virtual bool PrintMembers(StringBuilder builder)
    {
        RuntimeHelpers.EnsureSufficientExecutionStack();
        builder.Append("Name = ");
        builder.Append((object?)Name);
        builder.Append(", Address = ");
        builder.Append((object?)Address);
        builder.Append(", Email = ");
        builder.Append((object?)Email);
        return true;
    }

    [CompilerGenerated]
    public static bool operator !=(Person? left, Person? right)
    {
        return !(left == right);
    }

    [CompilerGenerated]
    public static bool operator ==(Person? left, Person? right)
    {
        return (object)left == right || (left?.Equals(right) ?? false);
    }

    [CompilerGenerated]
    public override int GetHashCode()
    {
        return ((EqualityComparer<Type>.Default.GetHashCode(EqualityContract) * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Name)) * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Address)) * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Email);
    }

    [CompilerGenerated]
    public override bool Equals(object? obj)
    {
        return Equals(obj as Person);
    }

    [CompilerGenerated]
    public virtual bool Equals(Person? other)
    {
        return (object)this == other || ((object)other != null && EqualityContract == other.EqualityContract && EqualityComparer<string>.Default.Equals(Name, other.Name) && EqualityComparer<string>.Default.Equals(Address, other.Address) && EqualityComparer<string>.Default.Equals(Email, other.Email));
    }

    [CompilerGenerated]
    protected Person(Person original)
    {
        Name = original.Name;
        Address = original.Address;
        Email = original.Email;
    }

    [CompilerGenerated]
    public void Deconstruct(out string Name, out string Address, out string Email)
    {
        Name = this.Name;
        Address = this.Address;
        Email = this.Email;
    }
}

 

 
【C#/.NET】record介绍

 可以看到,编译器给使用了record关键字的定义生成了对应的属性和构造函数,并且重写了ToString(),GetHashCode,Equals还有一个解构函数和!=和==运算符。其实看到这里就明白了,为什么record可以提供值比较,解构,hash等。

不可变性是因为record的属性是使用了init关键字而不是set,这样子如果对record的对象属性赋值,编译器会报错。

值相等性是重定义了!=和==运算符

hash是因为重写了GetHashCode,Equals

解构是定义了Deconstruct方法

结论

我们介绍了.NET 5中引入的record类型及其优点。但对于许多数据对象的简单情况,如值对象和DTO,推荐使用record类型。虽然record可以定义可变更的属性和添加方法,不过这样子有点违背了record的初衷。文章来源地址https://www.toymoban.com/news/detail-472950.html

到了这里,关于【C#/.NET】record介绍的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • c# Log4net使用介绍

    注意:将log4net.config的属性“复制到输出目录”设置为“始终复制” Log4net 是一个用于 .NET 平台的日志记录框架,它可以帮助开发者在应用程序中记录和管理日志信息,以便于调试和监控应用程序的运行情况。下面是 Log4net 的配置和使用过程及案例: 安装 log4net 可以通过 Nu

    2024年02月02日
    浏览(78)
  • 什么是HTTPS加密协议?HTTPS安全传输原理,SSL和TLS介绍,NGINX如何配置SSL证书

    HTTPS是超文本传输协议(HTTP)的安全版本。它使用SSL(安全套接层)或TLS(传输层安全)加密协议来保护数据传输的安全性和机密性,以防止未经授权的访问和窃听。HTTPS协议通常用于处理敏感信息,如在线支付或登录凭证等。可以通过URL的前缀来识别一个网站是否使用了H

    2024年02月03日
    浏览(60)
  • UE4 Take Recorder的使用

    1.设置镜头片段编号、帧率 2.添加要录制的对象 3.如果勾上,就会创建如下图的关卡序列文件 4.如果勾上,创建的关卡序列文件会自动锁定。可点击红框锁图标处解锁 5.选择“可拥有”,就不会实例化生成一个Light Source,勾选需要录制的属性 6.开始录制 7.记得保存你的预设。

    2024年02月12日
    浏览(51)
  • 使用Java 17中的record替代Lombok的部分功能

    在DD长期更新的Java新特性专栏中,已经介绍过Java 16中开始支持的新特性:record的使用。 之前只是做了介绍,但没有结合之前的编码习惯或规范来聊聊未来的应用变化。最近正好因为互相review一些合作伙伴的代码,产生了一些讨论话题,主要正针对于有了 record 之后,其实之前

    2024年02月02日
    浏览(43)
  • 使用Jmeter自带recorder代理服务器录制接口脚本

    脚本录制 配置线程组 添加代理服务器 端口 和 录制脚本放置位置可根据需要设置 启动录制 点击启动后 弹出创建证书提示,点击OK 这个证书后续需要使用到 然后可见 一个弹窗。 Recorder . 本质是代理服务+录制交易控制 可设置对应数据 方便录制脚本的查看 证书配置 Jmeter 证书

    2024年02月12日
    浏览(44)
  • volatile关键字原理的使用介绍和底层原理解析和使用实例

    volatile 的主要作用是保证可见性和有序性,禁止编译器优化。 保证可见性:当一个变量被声明为 volatile 之后,每次读取这个变量的值都会从主内存中读取,而不是从缓存中读取,这就保证了不同线程对这个变量操作的可见性。 有序性:volatile 保证了不同线程对一个 vo

    2024年02月02日
    浏览(42)
  • ZooKeeper 使用介绍和原理详解

    目录 1. 介绍 重要性 应用场景 2. ZooKeeper 架构 服务角色 数据模型 工作原理 3. 安装和配置 下载 ZooKeeper 安装和配置 启动 ZooKeeper 验证和管理 停止和关闭 4. ZooKeeper 数据模型 数据结构和层次命名空间: 节点类型和 Watcher 机制: 5. 分布式锁 实现分布式锁的基本步骤 代码示例(

    2024年02月04日
    浏览(32)
  • .net core中如何自定义静态文件目录、默认主页、和文件浏览目录?

    在.NET Core中,UseStaticFiles、UseDefaultFiles、UseDirectoryBrowser和UseFileServer中间件用于处理静态文件和目录浏览。下面我将为你提供一个简单的例子,演示它们的用法。 首先,确保你的项目已经安装了 Microsoft.AspNetCore.StaticFiles  NuGet包,因为这是这些中间件的依赖。 然后,打开  S

    2024年02月04日
    浏览(40)
  • 什么是Jmeter ?Jmeter使用的原理步骤是什么?

    Apache JMeter 是 Apache 组织开发的基于 Java 的压力测试工具。用于对软件做压力测试,它最初被设计用于 Web 应用测试,但后来扩展到其他测试领域。 它可以用于测试静态和动态资源,例如静态文件、Java 小服务程序、CGI 脚本、Java 对象、数据库、FTP 服务器, 等等。JMeter 可以用

    2024年02月07日
    浏览(58)
  • 关于在 Mybatis 中使用 record 关键字来定义 JavaBean

    经测试,正常情况下使用 record 是没有问题的,但若是使用了 resultMap,将会导致错误: 首先, record 类型没有 无参构造函数 ,所以在反射过程中无法创建对应类型,导致了 argument type mismatch 错误。 那如果给 record 类型的类加上无参构造函数呢? 会出现以下错误: 可以看到

    2024年02月05日
    浏览(93)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包