请选择 进入手机版 | 继续访问电脑版

[C#教程] C# Record构造函数的举动 更改详解

[复制链接]
查看45 | 回复5 | 2021-9-14 09:21:20 | 显示全部楼层 |阅读模式

怎样 更改 C# Record 构造函数的活动

Record[1] 是 C# 9 中的一个新功能。Record是从Structs[2]借用的特别 类, 由于 它们具有 基于值的相称 性,您可以将它们视为两类范例 之间的混合体。默认环境 下,它们或多或少是不可变的,并且具有语法糖,使声明更轻易 和更简洁。但是,语法糖大概 会掩饰 更多标准使命 ,比方 更改默认构造函数的活动 。在某些环境 下,您大概 必要 如许 做以举行 验证。本文将向您展示怎样 实现这一目的 。

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

  1. public class StringValidator
  2. {
  3. public string InputString { get; }
  4. public StringValidator(string inputString)
  5. {
  6. if (string.IsNullOrEmpty(inputString)) throw new ArgumentNullException(nameof(inputString));
  7. InputString = inputString;
  8. }
  9. }
复制代码

很显着 ,假如 消耗 者试图在没有有效 字符串的环境 下创建此类的实例,他们将收到非常 。创建Record的标准语法如下所示:

  1. public record StringValidator(string InputString);
复制代码

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

  1. public record StringValidator
  2. {
  3. public string InputString { get; }
  4. public StringValidator(string inputString)
  5. {
  6. if (string.IsNullOrEmpty(inputString)) throw new ArgumentNullException(nameof(inputString));
  7. InputString = inputString;
  8. }
  9. }
复制代码

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

为了答应 非粉碎 性突变,我们必要 添加init属性访问器。这与构造函数的工作方式雷同 ,但仅在对象初始化期间调用。这是实现init访问器的更完备 的办理 方案。这答应 您共享构造函数逻辑和初始化逻辑。

  1. using System;
  2. namespace ConsoleApp25
  3. {
  4. class Program
  5. {
  6. static void Main(string[] args)
  7. {
  8. //This throws an exception from the constructor
  9. //var stringValidator = new StringValidator(null);
  10. var stringValidator1 = new StringValidator("First");
  11. var stringValidator2 = stringValidator1 with { InputString = "Second" };
  12. Console.WriteLine(stringValidator2.InputString);
  13. //This throws an exception from the init accessor
  14. //var stringValidator3 = stringValidator1 with { InputString = null };
  15. //Output: Second
  16. }
  17. }
  18. public record StringValidator
  19. {
  20. private string inputString;
  21. public string InputString
  22. {
  23. get => inputString;
  24. init
  25. {
  26. //This init accessor works like the set accessor
  27. ValidateInputString(value);
  28. inputString = value;
  29. }
  30. }
  31. public StringValidator(string inputString)
  32. {
  33. ValidateInputString(inputString);
  34. InputString = inputString;
  35. }
  36. public static void ValidateInputString(string inputString)
  37. {
  38. if (string.IsNullOrEmpty(inputString)) throw new ArgumentNullException(nameof(inputString));
  39. }
  40. }
  41. }
复制代码

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

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

  1. using System.Net;
  2. namespace Urls
  3. {
  4. public record QueryParameter
  5. {
  6. private string? fieldValue;
  7. public string FieldName { get; init; }
  8. public string? Value
  9. {
  10. get => fieldValue; init
  11. {
  12. fieldValue = WebUtility.UrlDecode(value);
  13. }
  14. }
  15. public QueryParameter(string fieldName, string? value)
  16. {
  17. FieldName = fieldName;
  18. fieldValue = WebUtility.UrlDecode(value);
  19. }
  20. public override string ToString()
  21. => $"{FieldName}{(Value != null ? "=" : "")}{WebUtility.UrlEncode(Value)}";
  22. }
  23. }
复制代码

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

你大概 会问:为什么不把齐备 都Record下来?好像 会有与此干系 的陷阱,但我们正在冒险进入新范畴 ,我们尚未为 C# 上下文中的Record订定 最佳实践。

总结

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

到此这篇关于C# Record构造函数活动 更改的文章就先容 到这了,更多干系 C# 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


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

avatar 刘晨阳1 | 2021-9-19 18:31:17 | 显示全部楼层
读了admin楼主的帖子,顿时马桶就通了。。。
回复

使用道具 举报

avatar 风云18171265739 | 2021-10-2 00:36:37 | 显示全部楼层
admin楼主的头像能辟邪啊!
回复

使用道具 举报

avatar 恶贯满瘾锥 | 2021-10-4 04:07:25 | 显示全部楼层
视死如归的架势啊!
回复

使用道具 举报

avatar 一箫凝月黄 | 2021-10-4 04:07:28 | 显示全部楼层
世界末日我都挺过去了,看到admin楼主我才知道为什么上帝留我到现在!
回复

使用道具 举报

avatar 天使798 | 昨天 15:55 | 显示全部楼层
我对admin楼主的敬仰犹如滔滔江水绵延不绝!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则