当前位置: 首页 > 编程笔记 >

使用C#9中records作为强类型ID的实例教程

仲孙绍元
2023-03-14
本文向大家介绍使用C#9中records作为强类型ID的实例教程,包括了使用C#9中records作为强类型ID的实例教程的使用技巧和注意事项,需要的朋友参考一下

强类型ID

实体通常是整数,GUID或者string类型,因为数据库直接支持这些类型,但是,如果实体的ID的类型是一样的,比如都是整数的ID,这有可能会出现ID值传错的问题,看下边的示例。

public void AddProductToOrder(int orderId, int productId, int count)
{
 ...
}

...

// 这个地方,参数传错了
AddProductToOrder(productId, orderId, int count);

上面的代码可以很好地通过检查并编译,但是在运行的时候就出问题了,这是逻辑bug。

幸运的是,可以定义强类型id来解决这个问题,这个想法很简单,为每个实体的ID声明一个特定的类型,现在需要这样写:

// 使用强类型ID代替整数ID
public void AddProductToOrder(OrderId orderId, ProductId productId, int count)
{
 ...
}

...

// 这个地方,参数传错了
AddProductToOrder(productId, orderId, int count);

在上面的代码中,我们犯了与第一个示例相同的错误(交换productId和orderId),但是在这种情况下,类型不同,因此编译器会捕获该错误并报告错误,我们仍然需要对其进行修复,但是至少在生产中并没有爆炸。

编写一个强类型的id

public readonly struct ProductId : IEquatable<ProductId>
{
 public ProductId(int value)
 {
  Value = value;
 }
 
 public int Value { get; }

 public bool Equals(ProductId other) => other.Value == Value;
 public override bool Equals(object obj) => obj is ProductId other && Equals(other);
 public override int GetHashCode() => Value.GetHashCode();
 public override string ToString() => $"ProductId {Value}";
 public static bool operator ==(ProductId a, ProductId b) => a.Equals(b);
 public static bool operator !=(ProductId a, ProductId b) => !a.Equals(b);
}

上面的代码没什么难的,但是如果每个实体都需要的话,那确实有点麻烦,在C# 9 可以使用source generators来完成这些,但是C# 9还引入了另一个功能,使用起来更方便。

Record类型

Record 类型是具有内置不变性和值语义的引用类型,它和上面我们写的强类型是一样的(手动写的成员实现Equals,GetHashCode等等),在代码中使用也非常简洁, 如果我们ProductId使用record重写类型,就是下边这样:

public record ProductId(int Value);

是的,您没看错,这是一行,而上面的代码是一大段,它完成了我们手动执行的所有操作(实际上,还多了很多!)。

主要区别在于:我们的手动实现是struct,即值类型,但是记录是引用类型,这意味着它们可以为null,这可能不是主要问题,尤其是在使用可为空的引用类型的情况下,但是要知道这一点。

现在为模型中的每个实体编写一个强类型的id是不是很简单,使用Record 非常方便,当然,还有其他问题需要考虑,例如JSON序列化,与Entity Framework Core一起使用等,但这是另一篇文章的故事!

总结

到此这篇关于使用C#9中records作为强类型ID的文章就介绍到这了,更多相关C#9 records作强类型ID内容请搜索小牛知识库以前的文章或继续浏览下面的相关文章希望大家以后多多支持小牛知识库!

原文作者: thomas levesque

原文链接:https://thomaslevesque.com/2020/10/30/using-csharp-9-records-as-strongly-typed-ids/

 类似资料:
  • 本文向大家介绍C#编程中枚举类型的使用教程,包括了C#编程中枚举类型的使用教程的使用技巧和注意事项,需要的朋友参考一下 枚举类型(也称为枚举)为定义一组可以赋给变量的命名整数常量提供了一种有效的方法。例如,假设您必须定义一个变量,该变量的值表示一周中的一天。该变量只能存储七个有意义的值。若要定义这些值,可以使用枚举类型。枚举类型是使用 enum关键字声明的。 默认情况下,枚举中每个元素的基础类型是

  • 本文向大家介绍C#中Dictionary类使用实例,包括了C#中Dictionary类使用实例的使用技巧和注意事项,需要的朋友参考一下 在C#中,使用Dictionary类来管理由键值对组成的集合,这类集合称为字典。 字典最大的特点就是能够根据键来快速查找集合中的值。 下面是一个使用字典的小实例,希望通过这个小实例,能让大家对字典操作有一个初步的了解。下面是完整代码。 实例中需要定义两个类: Sc

  • 本文向大家介绍C语言泛型编程实例教程,包括了C语言泛型编程实例教程的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C语言泛型编程的方法,分享给大家供大家参考之用。具体分析如下: 首先,泛型编程让你编写完全一般化并可重复使用的算法,其效率与针对某特定数据类型而设计的算法相同。在C语言中,可以通过一些手段实现这样的泛型编程。这里介绍一种方法——通过无类型指针void* 看下面的一个实现交换两个

  • 本文向大家介绍C语言变量类型与输出控制用法实例教程,包括了C语言变量类型与输出控制用法实例教程的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C语言变量类型与输出控制用法,有助于读者很好的对其进行总结与归纳。该实例分享给大家供大家参考借鉴之用。具体如下: 完整实例代码如下: 感兴趣的读者可以测试运行一下本文实例,相信会有新的收获。

  • 1.3 弱类型强作用域 “弱类型”不是 VimL 的特点,是几乎所有脚本语言的特点。准确地说是变量无类型,但值 有类型。创建变量时不必定义类型,直接赋值就行,也可以认为是变量临时获得了值的类 型。关于 VimL 的变量与类型,将在下一章的基础语法中详解。 变量作用域是编程的另一个重要概念,也几乎每个语言都要管理的任务。这里说 VimL 具 有“强作用域”的特点,是指它提供了一种简明的语法,让用户强

  • 本文向大家介绍C#中lock死锁实例教程,包括了C#中lock死锁实例教程的使用技巧和注意事项,需要的朋友参考一下 在c#中有个关键字lock,它的作用是锁定某一代码块,让同一时间只有一个线程访问该代码块,本文就来谈谈lock关键字的原理和其中应注意的几个问题: lock的使用原型是: 首先要明白为什么上面这段话能够锁定代码,其中的奥妙就是X这个对象,事实上X是任意一种引用类型,它在这儿起的作用就