代码之家  ›  专栏  ›  技术社区  ›  Shea Daniels

.NET业务层中的结构与类

  •  7
  • Shea Daniels  · 技术社区  · 17 年前

    我现在正在上“高级”ASP.NET课程,我的导师只是提出了一个我不确定的观点。(我说“高级”是因为他仍在使用HTML表进行页面布局,我们刚刚讨论了母版页的非常高级的主题。我需要漂白剂!)

    他指出,不应该创建包含所有适用数据和方法的Person类,而是应该创建Person结构和Person类。结构包含通常为Person类的属性,而类只包含方法。由于person结构位于堆栈上,因此只要方法或任何内容从堆栈中弹出,与您的人员关联的数据就会消失,而不是像对象一样在堆中被垃圾收集。

    这应该可以节省内存并使垃圾收集过程更快。

    问题是:这会产生多大的影响?它真的值得吗?

    6 回复  |  直到 17 年前
        1
  •  7
  •   LBushkin    17 年前

    为您描述的模式提供的推理有几个问题。

    第一, 结构不是 总是 在堆栈上分配 . 只有当方法中的are参数或本地实例时,才会对它们进行堆栈分配。定义为类成员的结构实际上是堆分配的。因此,只有在某些狭窄的上下文中,结构由于减少了垃圾收集的工作而更有效的论点才是正确的。

    第二, 结构的任何非valuetype成员也在堆上分配 (例如字符串)。因此,即使结构可以从堆栈中弹出,它引用的任何堆对象都必须被垃圾收集。

    第三, 结构很少保存内存,因为当作为方法参数传递时,它们具有值语义 .这基本上意味着一个结构的副本被创建和传递,而不是对现有结构的引用——这在内存上是不可能便宜的。当您看到其他响应说可变结构可能有问题时——这是因为(和其他一些响应一起)由于结构是按值传递的,所以对原始结构的更改对生成结构副本的位置不可用。这可能会导致您违反程序中的假设或期望,在该程序中,您可能已经实际需要结构的引用语义。


    就我个人而言,我发现创建DTO对象(无论是类还是结构)以嵌套在业务层对象中的模式似乎没有多大好处。除非您有一个持久性或表示层, 专门利用这种模式 要跨层传递信息,我看不到太大的价值。

    此外,使用结构作为DTO对象的具体情况似乎有缺陷,因为它引入了不必要的冗余。因为结构不能继承其他结构,所以不能表示IS-A关系。当你有一个从别人那里继承的客户时,你会怎么做?是否重复customer结构中的所有person属性?是否在客户结构中嵌套一个person结构?这两种方法都不理想。如果您至少使用了类,那么您可以让客户扩展人员。

        2
  •  10
  •   Andrew Hare    17 年前

    说实话,我不相信你会从中看到很多性能上的好处。结构很难写得好,写得差的结构比向垃圾收集器征税危险得多。

    听起来你的教授提倡使用 data transfer objects 这将鼓励国家和行为的分离。如果处理得当,这可能是一个好的设计(在大多数情况下,您将使用类而不是结构实现此模式)。

    我说使用一个结构可能更危险的原因是,值类型被clr处理得更为不同,如果写得不好(例如,一个可变的结构),可能会造成可怕的头痛。另外,如果您的类型包含许多字段,然后从一个方法传递给另一个方法,那么您将在每个方法调用上复制每个字段的值,从而使用比最初使用类更多的内存。

        3
  •  2
  •   Tad Donaghe    17 年前

    我觉得这很傻。我不知道在HTML中使用表格进行布局的人的编码建议中我放了多少存货。如果这是一种产生显著优势的技术,那么它将是一种标准实践。不是。这是我第一次听说这种技术。

        4
  •  1
  •   Dan Goldstein    17 年前

    不管这个策略是否更有效,它将更难与之合作,我会尽量避免它。尽管如此,我怀疑这样做是否更有效率。如果是的话,编译器可能会以这种方式自动实现它。依赖编译器进行语言级优化通常是安全的。

        5
  •  0
  •   Mike Hofer    17 年前

    老实说,这是我第一次听说这种方法。

    据我所知,结构是值类型。通常,如果结构小于16个字节、不可变、不必装箱,并且表示类似于基元类型的单个值,则需要定义该结构。

    MSDN, where Microsoft has published structure design guidelines.

    像你的老师所说的意志课 容易地 扩展到16字节规则之后。很难看到这种性质的结构没有将业务(或者至少是验证)规则封装到属性中。在我看来,这是一个相当劣质的设计。

        6
  •  -2
  •   Joseph    17 年前

    这种方法的问题在于对象(类的实例化)具有可变状态。相反,结构应该是不可变的,这意味着它们没有可以更改的状态。在典型的应用程序中,业务层大量利用对象状态的变化(即工作流、验证等)。

    他所描述的好处并不保证这会带来缺点。

    推荐文章