尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

第一出:record 类型

第一出:record 类型
📅 发布时间:2026/7/3 3:02:35

我还是用原词吧,我知道有翻译为“记录类型”的说法。只是,只是,老周老觉得这不太好听,可是老周也找不出更好的词语,还是用回 record吧。

record 是引用类型,跟 class 很像(确实差不多)。那么,用人民群众都熟悉的 class 不香吗,为何要新增个 record 呢?答:为了数据比较的便捷。

不明白?没事,往下看。最近有一位热心邻居送了老周一只宠物:

public class Cat { public string Nick { get; set; } public string Name { get; set; } public int Age { get; set; } }

这只新宠物可不简单,一顶一的高级吃货。鱼肉、猪肉、鸡腿、饼干、豆腐、面包、水果、面条、小麦、飞蛾……反正,只要它能塞进嘴里的,它都吃。

接下来,我们 new 两个宠物实例。

// 两个实例描述的是同一只猫 Cat pet1 = new Cat { Nick = "松子", Name = "Jack", Age = 1 }; Cat pet2 = new Cat { Nick = "松子", Name = "Jack", Age = 1 }; // 居然不是同一只猫 Console.WriteLine("同一只?{0}", pet1 == pet2);

其实,两个实例描述的都是我家的乖乖。可是,输出的是:

同一只?False

这是因为,在相等比较时,人家关心的类型引用——引用的是否为同一个实例。但是,在数据处理方案中,我们更关注对象中的字段/属性是否相等,即内容比较。

现在,把 Cat 的声明改为 record 类型。

public record Cat { public string Nick { get; set; } public string Name { get; set; } public int Age { get; set; } }

然后同样用上面的 pet1 和 pet2 实例进行相等比较,得到预期的结果:

同一只?True

record 类型让你省去了重写相等比较(重写 Equals、GetHashCode 等方法或重载运算符)的逻辑。

实际上,代码在编译后 record 类型也是一个类,但自动实现了成员相等比较的逻辑。以前你要手动去折腾的事现在全交给编译器去干。

假如,有一个 User 类型,用于表示用户信息(包括用户名、密码),然后这个 User 类型在数据处理方案中可能会产生N多个实例。例如你根据条件从EF模型中筛选出一个 User 实例 A,根据用户输入的登录名和密码产生了 User 实例 B。为了验证用户输入的登录信息是否正确,如果 User 是 class,你可能要这样判断:

if(A.UserName == B.UserName && A.Password == B.Password) { .................. }

但要是你把 User 定义为 record 类型,那么,一句话的工夫:

A == B

第二出:模式匹配(Pattern Matching)

"模式匹配"这个翻译感觉怪怪滴,老周还没想出什么更好的词语。模式匹配并不是什么神奇的东西,它只是在对变量值进行检测时的扩展行为。以前,老感觉C++/C# 的 switch 语句不够强大,因为传统的用法里面,每个 case 子句只能比较单个常量值。比如

int 考试成绩 = 85; switch (考试成绩) { case 10: Console.WriteLine("才考这么点破分啊"); break; case 50: Console.WriteLine("还差一点,就合格了"); break; case 85: Console.WriteLine("真是秀"); break; case 90: Console.WriteLine("奇迹发生"); break; }

我幻想着,要是能像下面这样写就好了:

switch (考试成绩) { case 0: Console.WriteLine("缺考?"); break; case > 0 && <= 30: Console.WriteLine("太烂了"); break; case > 30 && < 60: Console.WriteLine("还是不行"); break; case >= 60 && < 80: Console.WriteLine("还得努力"); break; case >= 80 && < 90: Console.WriteLine("秀儿,真优秀"); break; case >= 90 && <= 100: Console.WriteLine("不错,奇迹"); break; }

等了很多年很多年(“千年等一回,等……”)以后,终于可以实现了。

switch (考试成绩) { case 0: Console.WriteLine("缺考?"); break; case > 0 and <= 30: Console.WriteLine("太烂了"); break; case > 30 and < 60: Console.WriteLine("还是不行"); break; case >= 60 and < 80: Console.WriteLine("还得努力"); break; case >= 80 and < 90: Console.WriteLine("秀儿,真优秀"); break; case >= 90 and <= 100: Console.WriteLine("不错,奇迹"); break; }

哟西,真香。

有时候,不仅要检测对象的值,还得深入到其成员。比如下面这个例子,Order类表示一条订单信息。

public class Order { public int ID { get; set; } public string Company { get; set; } public string ContactName { get; set; } public float Qty { get; set; } public decimal UP { get; set; } public DateTime Date { get; set; } }

前不久,公司接到一笔Order,做成了收益应该不错。

Order od = new Order { ID = 11, Company = "大嘴狗贸易有限公司", ContactName = "陈大爷", Qty = 425.12f, UP = 1000.55M, Date = new(2020, 10, 27) };

假如我要在变量 od 上做 switch,看看,就这样:

switch (od) { case { Qty: > 1000f }: Console.WriteLine("发财了,发财了"); break; case { Qty: > 500f }: Console.WriteLine("好家伙,年度大订单"); break; case { Qty: > 100f }: Console.WriteLine("订单量不错"); break; }

咦?这,这是什么鬼?莫惊莫惊,这不是鬼。它的意思是判断 Qty 属性的值,如果订单货量大于 100 就输出“订单量不错”;要是订单货量大于 1000,那就输出“发财了,发财了”。

但你会说,这对大括号怎么来的呢?还记得这种 LINQ 的写法吗?

from x in ... where x.A ... select new { Prop1 = ..., Prop2 = ..., ................ }

new { ... } 是匿名类型实例,那如果是非匿名类型呢,看看前面的 Cat 实例初始化。

Cat { .......... }

这就对了,这对大括号就是构造某实例的成员值用的,所以,上面的 switch 语句其实是这样写的:

switch (od) { case Order{ Qty: > 1000f }: Console.WriteLine("发财了,发财了"); break; case Order{ Qty: > 500f }: Console.WriteLine("好家伙,年度大订单"); break; case Order{ Qty: > 100f }: Console.WriteLine("订单量不错"); break; }

Order{ ... } 就是匹配一个 Order 对象实例,并且它的 Qty 属性要符合 ... 条件。由于变量 od 始终就是 Order 类型,所以,case 子句中的 Order 就省略了,变成

case { Qty: > 1000f }: Console.WriteLine("发财了,发财了"); break;

如果出现多个属性,则表示为多个属性设定匹配条件,它们之间是“且”的关系。比如

case { Qty: > 100f, Company: not null }: Console.WriteLine("订单量不错"); break;

猜猜啥意思?这个是可以“望文生义”的,Qty 属性的值要大于 100,并且 Company 属性的值不能为 null。不为 null 的写法是 not null,不要写成 !null,因为这样太难看了。

如果你的代码分支较少,你可以用 if 语句的,只是得配合 is 运算符。

if (od is { UP: < 3000M }) { Console.WriteLine("报价不理想"); }

但是,这个写法目前有局限性,它只能用常量值来做判断,你要是这样写就会报错。

if (od is { Date: < DateTime.Now }) { ................ }

DateTime.Now 不是常量值,上面代码无法通过编译。

is 运算符以前是用来匹配类型的,上述的用法是它的语法扩展。

object n = 5000000L; if(n is long) { Console.WriteLine("它是个长整型"); }

进化之后的 is 运算符也可以这样用:

object n = 5000000L; if(n is long x) { Console.WriteLine("它是个长整型,存放的值是:{0}", x); }

相关新闻

  • 2026年健康早餐新选择:揭秘最受欢迎的苦荞片品牌
  • react hook 原理
  • AI Agent赋能外贸客户开发:从电梯行业实战看自动化精准获客

最新新闻

  • CPPM注册职业采购经理怎么报名?报考条件、费用和证书查询一次说清
  • 支付系统重复收费难题:幂等键依赖的四个假设及应对之策
  • 3分钟掌握BurpCrypto插件:实战DES加密登录接口自动化测试
  • Java 必看:如何正确重写 hashCode() 和 equals() 方法?
  • ZCode对接商汤免费模型全流程教程
  • 从提示词工程到 Harness Engineering:打造坚实可靠的 AI 开发系统

日新闻

  • JMeter接口测试实战:从核心元件到复杂场景构建
  • Java Applet版刽子手游戏源码:含完整项目结构、吊杆绘图与胜负逻辑
  • 使用Apache JMeter对RoadRunner PHP应用进行性能测试与调优指南

周新闻

  • Windows字体自定义终极方案:No!! MeiryoUI完全指南
  • Deepin Boot Maker:告别命令行,3分钟制作Linux启动盘的智能解决方案
  • Plain Craft Launcher 2:重新定义你的Minecraft游戏体验

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号