如何更改 C# Record 构造函数的行为

如何更改 C# Record 构造函数的行为

Record[1] 是 C# 9 中的一个新功能。Record是从Structs[2]借用的特殊类, 因为它们具有 基于值的相等性,您可以将它们视为两类类型之间的混合体。默认情况下,它们或多或少是不可变的,并且具有语法糖,使声明更容易和更简洁。但是,语法糖可能会掩盖更多标准任务,例如更改默认构造函数的行为。在某些情况下,您可能需要这样做以进行验证。本文将向您展示如何实现这一目标。

以这个简单的示例类为例:

public class StringValidator
{public string InputString { get; }public StringValidator(string inputString){if (string.IsNullOrEmpty(inputString)) throw new ArgumentNullException(nameof(inputString));InputString = inputString;}
}

很明显,如果消费者试图在没有有效字符串的情况下创建此类的实例,他们将收到异常。创建Record的标准语法如下所示:

    public record StringValidator(string InputString);

它既友好又简洁,但并不清楚您将如何验证字符串。此定义告诉编译器将有一个名为 的属性InputString,并且构造函数会将值从参数传递给该属性。我们需要删除语法糖来验证字符串。幸运的是,这很容易。我们不需要使用新语法来定义我们的Record。我们可以定义类似于类的Record,但将关键字类更改为Record。

public record StringValidator
{public string InputString { get;  }public StringValidator(string inputString){if (string.IsNullOrEmpty(inputString)) throw new ArgumentNullException(nameof(inputString));InputString = inputString;}
}

不幸的是,这意味着我们不能使用 非破坏性突变[3]。该with关键字给我们创造了一些属性来更改Record的新版本的功能。这意味着我们不会修改Record的原始实例,但我们会得到它的副本。这是 Fluent API 和函数式编程的常用方法。这使我们能够保持不变性。

为了允许非破坏性突变,我们需要添加init属性访问器。这与构造函数的工作方式类似,但仅在对象初始化期间调用。这是实现init访问器的更完整的解决方案。这允许您共享构造函数逻辑和初始化逻辑。

using System;namespace ConsoleApp25
{class Program{static void Main(string[] args){//This throws an exception from the constructor//var stringValidator = new StringValidator(null);var stringValidator1 = new StringValidator("First");var stringValidator2 = stringValidator1 with { InputString = "Second" };Console.WriteLine(stringValidator2.InputString);//This throws an exception from the init accessor//var stringValidator3 = stringValidator1 with { InputString = null };//Output: Second}}public record StringValidator{private string inputString;public string InputString{get => inputString;init{//This init accessor works like the set accessorValidateInputString(value);inputString = value;}}public StringValidator(string inputString){ValidateInputString(inputString);InputString = inputString;}public static void ValidateInputString(string inputString){if (string.IsNullOrEmpty(inputString)) throw new ArgumentNullException(nameof(inputString));}}
}

Record构造函数应该有逻辑吗?

这是一个有争议的辩论,超出了本文的范围。很多人会争辩说你不应该把逻辑放在构造函数中。Record的设计鼓励您不要在构造函数或 init 访问器中放置逻辑。一般来说,Record应该及时代表数据的快照状态。您不需要应用逻辑,因为假设您知道此时数据的状态。但是,就像其他所有编程结构一样,无法知道Record可能会产生哪些用例。这是库 Urls 中的[4]一个示例[5], [6]它将 URL 视为不可变Record:

using System.Net;namespace Urls
{public record QueryParameter{private string? fieldValue;public string FieldName { get; init; }public string? Value{get => fieldValue; init{fieldValue = WebUtility.UrlDecode(value);}}public QueryParameter(string fieldName, string? value){FieldName = fieldName;fieldValue = WebUtility.UrlDecode(value);}public override string ToString()=> $"{FieldName}{(Value != null ? "=" : "")}{WebUtility.UrlEncode(Value)}";}
}

我们确保在存储查询值时对其进行解码,然后在将其用作 Url 的一部分时对其进行编码。

你可能会问:为什么不把一切都Record下来?似乎会有与此相关的陷阱,但我们正在冒险进入新领域,我们尚未为 C# 上下文中的Record制定最佳实践。

总结

开发人员需要几年时间才能接受Record并制定使用它们的基本规则。您目前有一张白纸,您可以自由尝试,直到“专家”开始告诉您其他情况。我的建议是只使用Record来表示固定数据和最小逻辑。尽可能使用语法糖。但是,在某些情况下,构造函数中的最小验证可能是可行的。运用你的判断力,与你的团队讨论,权衡利弊。

References

[1] Record: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/records
[2] Structs: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct
[3] 非破坏性突变: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/records#non-destructive-mutation
[4] Urls 中的: https://github.com/MelbourneDeveloper/Urls
[5] 示例: https://github.com/MelbourneDeveloper/Urls/blob/5f55a9437cfac1223711d616bfdbeb72b230d263/src/Uris/QueryParameter.cs#L5
[6] , : https://github.com/MelbourneDeveloper/Urls

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/299118.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java克鲁斯卡尔算法_Java语言基于无向有权图实现克鲁斯卡尔算法代码示例

所谓有权图,就是图中的每一条边上都会有相应的一个或一组值。通常情况下,这个值只是一个数字如:在交通运输网中,边上的权值可能表示的是路程,也可能表示的是运输费用(显然二者都是数字)。不过,边上的权值也…

[原]一步一步自己制作弹出框

说到javascript弹出框的制作,将其实现步骤分开,其实很容易。下面,将拆分页面弹出框的制作步骤。首先,准备编辑工具(废话),其实,您可以使用notepad..嘿嘿。弹出框的组成结构: 1.一个页面遮罩层。 2.一个di…

那些你从未见过的神奇物理化学实验,今天全给你整理了!

全世界只有3.14 % 的人关注了爆炸吧知识1.电荷吸引水流2.比空气重的六氟化硫六氟化硫(SF6),法国两位化学家Moissan和Lebeau于1900年合成的人造惰性气体,具有良好的电气绝缘性能及优异的灭弧性能,是一种优于空气和油之间…

Makefile 使用总结

1. Makefile 简介 Makefile 是和 make 命令一起配合使用的. 很多大型项目的编译都是通过 Makefile 来组织的, 如果没有 Makefile, 那很多项目中各种库和代码之间的依赖关系不知会多复杂. Makefile的组织流程的能力如此之强, 不仅可以用来编译项目, 还可以用来组织我们平时的一些…

学C#的感想

我学C#已经一个学期了,却发现自己对C#的了解只是一点皮毛而已,根本什么都不能做。自己也试过去编写一些写程序,但就是只会那些简单的,一旦遇到复杂点的程序,就是狗咬乌龟—无从下口了。现在回想,都不知道自…

ASP.NET Core使用Middleware有条件地允许访问路由

问题有时,我们可能在Web API中包含一些具有调试功能的请求。比如我们上次的文章中“晕了!这个配置值从哪来的?”使用的获取配置值的功能:endpoints.MapGet("/test2/{key:alpha}", async context > {var key context…

java匹配两个字符_·代表任意一个字符,*代表任意一串字符,判断两个字符串是否匹配?...

代表任意一个字符,*代表任意一串字符,判断两个字符串是否匹配? 如题,代表任意一个字符,*代表任意一串字符,判断两个字符串是否匹配?假如a字符串为:as*bncb,b字符串为asdfgvbbnchb,则…

如何用最低的成本教育出最棒的孩子?看完这些公众号你就知道了

全世界只有3.14 % 的人关注了爆炸吧知识真正决定人与人之间的差距的,其实是我们对事物的见识与内心的格局,见识的深浅决定人生的深浅,格局的大小决定了人生之路是宽是窄。今天给大家推荐几个有深度、有想法的公众号,希望能够给你带…

Virtualbox 无缝整合linux和windows双系统

一直以来,为了使用公司规定的内部通信工具RTX, 而不得不在ubuntu上安装一个virtualbox以运行RTX, 但是由于是运行在虚拟机里面,所以经常不能及时的回复同时的消息,而造成沟通的延迟。 所以就想着,能不能及时的在ubuntu上面看到…

archlinux yaourt安装 以及出错细节 database file for archlinuxfr does not exist.

archlinux yaourt安装 但一直报错如下: :: Synchronizing package databases... core is up to date   extra is up to date   community is up to date  error: failed retrieving file archlinuxfr.db from repo.archlinuxcn.org : The requested URL …

WCF分布式开发常见错误(10):套接字连接中断,The socket connection was aborted

(使用Windows Service作为宿主的时候也会出现这样的情况,搜索的) 我们这里是自定义托管宿主,在进行WCF编程开发过程时,使用NetTcpBinding绑定协议,作为通讯协议,可能会引发这样的异常&#xff0…

聊一聊对外API接口的存活检查可以怎么做

背景 公司内部的API接口一般会分为两大类,一类是直接暴露在公网可以访问的,一类是只能在局域网内访问的。暴露在公网的一般就是业务网关以及一些和第三方公司有着某些合作,从而进行数据交互的接口。检查API接口是否存活,第一反应应…

mysql slave 1032_修复mysql slave复制1032错误

一台从库出现1032错误,那1032是什么错误,我们看一下[rootBLAVDP021 ~]# perror 1032MySQL error code 1032 (ER_KEY_NOT_FOUND): Cant find record in %-.192s简单说,就是在从库上找不到相应的记录,同时在show slave status\G;中有相关输出&a…

各种机械原理动态图,看完脑洞大开,绝对涨姿势!

全世界只有3.14 % 的人关注了爆炸吧知识1.钥匙开锁2.撬锁3.汽车换挡4.手枪上膛发射5.炮弹发射原理6.手雷爆炸7.洗衣机8.缝纫机9.心脏10. 近视眼手术:原理其实很简单,就是把角膜削成一个“隐形眼镜”。11.零钱分类12.吹号转载来源:物理好教师部…

HDOJ 1875 HDU 1875 畅通工程再续 ACM 1875 IN HDU

MiYu原创, 转帖请注明 : 转载自 ______________白白の屋题目地址: http://acm.hdu.edu.cn/showproblem.php?pid1875题目描述:畅通工程再续Time Limit: 2000/1000MS (Java/Others) Memory Limit: 32768/32768K (Java/Others)Total Submission(s): 3822Accepted Subm…

CSharp设计模式读书笔记(10):装饰模式(学习难度:★★★☆☆,使用频率:★★★☆☆)...

装饰模式(Decorator Pattern): 动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。 模式角色与结构: 示例代码: using System; using System.Collections.Generic; using Syste…

ShardingCore 如何呈现“完美”分表

这篇文章是我针对efcore的分表的简单介绍,如果您有以下需求那么可以自己选择是否使用本框架,本框架将一直持续更新下去,并且免费开源为.net生态做贡献,如果您觉得不错那么请帮忙点个star谢谢,框架地址[sharding-core](https://github.com/xuejmnet/shard…

使用javascript oop开发滑动(slide) 菜单控件

这里使用原生的javascript,用面向对象的方式创建一个容易维护使用方便的滑动菜单,调用方式如下:var$sliding document.getElementById("silding");vars1 newSliding();s1.commands $sliding.getElementsByTagName("dt");…

这段代码什么意思啊?

这段代码什么意思啊? Delphi / Windows SDK/APIhttp://www.delphi2007.net/DelphiDB/html/delphi_20061217214802252.htmlprocedure TForm3.RadioButton3Click(Sender: TObject); begin ADOTable1.refresh; with ADOTable1 do try disablecontrols; filte…

他毕业于北师大,编写了我国首套数学教材,陈景润华罗庚都崇拜他

全世界只有3.14 % 的人关注了爆炸吧知识要说起我国著名的数学家,很多人会想到陈景润、华罗庚等人,这些大数学家为我国数学研究做出了卓越贡献,也深深影响了很多人。那么,像陈景润、华罗庚这些大数学家,他们学习数学有受…