为什么应该用record来定义DTO

DTO

DTO是数据传输对象(Data Transfer Object)的简称,主要用作在进程之间传送数据。

DTO的特点是它不包含任何业务逻辑或行为。

下面是一个典型的DTO定义:

public class UserDto
{
    public int Id { get; set; }
    public string Name { get; set; }
}

DTO的不变性

在实际使用中,我们并没有在进程之间来回传输具体的对象,而是使用某种形式的序列化,因此,DTO的属性不需要更改。

另外,考虑到DTO的用途,如果DTO的属性在传输过程中发生变化,数据将不再准确。

所以,DTO应该以无法更改的方式创建——它们应该是不可变的。

class实现方式

为什么以前没强调过DTO的不变性呢?因为在C#中实现是一件比较麻烦的事。

虽然我们可以定义私有setter来实现不可变类型,例如:

public class UserDto
{
    public UserDto(int id, string name)
    {
        this.Id = id;
        this.Name = name;
    }
    public int Id { get; private set; }
    public string Name { get; private set; }
}

从下图我们可以看到,值必须通过构造函数传递给属性。

而且正如预期的那样,我们无法在创建对象后再为属性赋值:

为什么应该用record来定义DTO

然而,这种方法有个很明显的缺点,如果我们增加一个属性,就必须调整一次构造函数。

record实现方式

从C# 9开始,可以使用record关键字定义一个引用类型,用来提供用于封装数据的内置功能。

它在设计上就具备创建具有不可变属性的能力。例如:

public record UserDto(int Id, string Name);

是不是非常简洁!

注意我们定义的是属性,所以参数用的PascalCase。

而且从下图我们可以看到,它与class创建对象方式相同。

同样在创建对象后不能再为属性赋值:

为什么应该用record来定义DTO

另外有一个附带的好处,如果增加了属性,立刻可以知道哪些代码位置需要修改:

public record UserDto(int Id, string Name, string Address);
为什么应该用record来定义DTO

结论

在本文中,我们介绍了record类型,它使得在C#中使用不可变DTO变得非常简单。

如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“,记住我!

原文出处:公众号”My IO“

原文链接:https://mp.weixin.qq.com/s/Vd4aZFFNYPeM2IjkJQXlxQ

本文观点不代表Dotnet9立场,转载请联系原作者。

发表评论

登录后才能评论