C# DTOs。属性还是字段?

C# DTOs。属性还是字段?,c#,wcf,soa,dto,C#,Wcf,Soa,Dto,我需要创建一些DTO类来跨WCF传输业务对象 因为这些都是没有功能的数据包,有什么理由我不能只使用字段,或者有什么好的理由将它们作为属性正确公开 //fields [DataContract] class CustomerDTO { [DataMember] public int Id; [DataMember] public string Name; } //or properties? [DataContract] class CustomerDTO {

我需要创建一些DTO类来跨WCF传输业务对象

因为这些都是没有功能的数据包,有什么理由我不能只使用字段,或者有什么好的理由将它们作为属性正确公开

//fields
[DataContract]
class CustomerDTO
{
    [DataMember] public int     Id;
    [DataMember] public string  Name;
}

//or properties?
[DataContract]
class CustomerDTO
{
    [DataMember] public int    Id               { get; set; }
    [DataMember] public string Name             { get; set; }
}

我从不直接公开字段,大多数公司在标准中都禁止这样做。实际上,您完全抛弃了封装。DTO是更复杂事物的贫乏表示,这是一种奇怪的情况,因为它们的属性几乎破坏了封装。就我个人而言,我会使用这些属性,因为这就是它们的用途。如果需要的话,它还可以让你实现“脏”功能等。如果你直接调整字段,这并不容易

因为这些都是没有功能的数据包,有什么理由我不能只使用字段吗

这里没有反对公共领域的有力论据。但请务必认识到,这只是因为DTO中没有逻辑(行为),所以封装的正常参数不成立


我还是更喜欢酒店,但这里其实不需要

DataMember属性将同时适用于公共字段和属性,因此两者都是可能的。然而,我建议坚持使用属性

特别是,如果您使用的是StyleCop,那么您将被破坏


此规则存在的原因实际上并不适用于您的情况,但如果您在持续集成服务器上运行StyleCop验证作为构建的一部分,那么它仍然是一个维护问题。

您可以使用这两种方法。因为它不会影响性能,所以使用属性会更安全,以防遇到不适用于公共字段的序列化框架或类似框架


请注意,WCF代理生成将在客户端创建具有公共属性及其支持私有字段的DTO,即使您在服务端使用公共字段也是如此。如果您不希望这样,您需要在服务和客户机之间共享一个DTO库

如果我不介意的话,我最喜欢带有只读字段的不可变DTO:

public class CustomerDTO
{
    public CustomerDTO(int id, string name)
    {
        Id = id;
        Name = name;
    }

    public readonly int     Id;
    public readonly string  Name;

    // Override Equals and GetHashCode as well...
}
不可变记录有很多优点,比如结构平等,这使得自动测试断言的编写更加简单。它也是

不过,这取决于序列化程序。JSON.NET可以处理不可变记录,但许多其他序列化程序不能

对于那些处理公共字段的人,我更喜欢字段而不是属性,只是因为它更诚实

有些序列化程序坚持使用公共属性,不序列化字段。如果是这样的话,你就得这么做


老实说,考虑到我在这方面花了多少心思,这并不是让我晚上睡不着的真正原因,因为最终。因此,OOD规则实际上并不适用于DTO。

这里有两个属性优于字段的优点,我没有看到其他人提到过

  • 语法中的摩擦与功能完全匹配
  • 我认为默认行为应该是更安全的选择。对于字段,默认行为允许可变性,这是更危险的选项。必须添加关键字
    readonly
    ,以使字段不可变(在构造函数之外)。相反,自动属性的默认状态是不可变的;语法
    set才能使属性可变(在构造函数之外)

  • 中给出的引用计数
  • 与字段不同,在Visual Studio中查看属性有一个“代码镜头”,其中包括其引用计数。由于这些附加信息,我能够比字段更快地理解和重构属性。当然,可以使用Shift+F12在VisualStudio中搜索字段和属性之类的引用,但这是一个额外的步骤,需要时间。此外,在极少数情况下,一些项目包括多个目标。这使得Shift+F12搜索结果更难使用,因为对每个目标都执行搜索。在合同中,物业代码Len中给出的参考计数与项目目标数量无关

    结论
    不过,为了直接回答这个问题,我更喜欢使用可变属性(而不是显式构造函数),以确保使用序列化库中最快乐的路径(如中所述)。

    如果解决方案将这些DTO放置在特定位置,则可以在此特定规则上使用stylecop覆盖,就为了那个位置。的确,但这仍然是一个需要解决的维护问题。谢谢大家。将使用属性纯粹是为了一致性。将逻辑隐藏到属性中不是很容易混淆吗?属性的一个问题是,如果属性具有结构类型,访问该结构的任何部分都需要创建整个内容的额外临时副本。在公开结构域时,这种浪费性的复制操作是不必要的。这是一个非常好的答案。上周我突然想到为什么我们需要房产。它们不会增加任何价值。DTO纯粹是数据传输,因此不会表现出任何行为。不变的DTO似乎要优越得多。我确信我在某个地方读到过关于不在构造函数中设置属性的内容。我不知道这些信息在网上的什么地方。我以前已经想过很多次了。你最终决定了什么?@JonathanPeel那是很久以前的事了,但我想我只是选择了房产。最近的答案为字段提供了很好的理由。