简体   繁体   English

在.NET业务层中构造Vs类

[英]Structs Vs Classes in .NET Business Layer

I'm stuck in an "advanced" ASP.NET class right now and my instructor just put forth an opinion that I'm not sure about. 我现在陷入了一个“高级”ASP.NET课程,我的导师只是提出了一个我不确定的观点。 (I say "advanced" because he's still using HTML tables for page layout and we just talked about the incredibly advanced topic of Master Pages. I need eye bleach!) (我说“高级”,因为他仍然使用HTML表格进行页面布局,我们刚刚讨论了Master Pages非常高级的主题。我需要眼睛漂白!)

He states that instead of, say, creating a Person class that contains all of the data and methods applicable, you should create both a Person struct and and Person class. 他声明,创建一个包含所有适用的数据和方法的Person类,而不是创建Person类和Person类。 The struct contains what would normally be the properties for the Person class, and the class contains only methods. 该结构包含通常为Person类的属性,该类仅包含方法。 Since the Person struct sits on the stack, the data associated with your person goes away as soon as your method or whatever pops off of the stack instead of being garbage collected on the heap as with an object. 由于Person结构位于堆栈上,因此只要您的方法或任何弹出堆栈而不是像堆栈一样在堆上进行垃圾收集,与您的人员关联的数据就会消失。

This is supposed to save memory and make the garbage collection process faster. 这应该可以节省内存并使垃圾收集过程更快。

The question is: How big of an effect could this produce and is it really worth it? 问题是:这会产生多大的影响并且真的值得吗?

To be totally honest I don't believe you will see much of a performance benefit from doing this. 说实话,我不相信你会从中看到很多性能上的好处。 Structs are hard to write well and a poorly written struct is far more dangerous than taxing the garbage collector. 结构难以写好,写得不好的结构比对垃圾收集器征税要危险得多。

It sounds like your professor is advocating the use of data transfer objects which would encourage the separation of state and behavior. 听起来你的教授主张使用数据传输对象 ,这会鼓励状态和行为的分离。 This can be a good design if done properly (and in most cases you would implement this pattern using classes, not structs). 如果正确完成,这可能是一个很好的设计(在大多数情况下,您将使用类而不是结构来实现此模式)。

The reason I say that using a struct may be more dangerous is that value types are handled much more differently by the CLR and if written poorly (eg a mutable struct) can create terrible headaches. 我说使用结构可能更危险的原因是CLR处理的值类型更加不同,如果写得不好(例如可变结构)会产生可怕的麻烦。 Also, if your type contains many fields and then is passed from method to method you will be copying every field's value on each method call thus using more memory than if you had used a class in the first place. 此外,如果您的类型包含许多字段,然后从方法传递到方法,您将在每个方法调用上复制每个字段的值,因此使用的内存比您在第一个地方使用类时使用的内存更多。

There are several issues with the reasoning presented for pattern you describe. 针对您描述的模式提出的推理存在几个问题。

First, structs are not always allocated on the stack . 首先, 结构并不总是在堆栈上分配 They are only stack-allocated when the are parameters to or local instances within a method. 它们仅在方法中的参数或本地实例时进行堆栈分配。 A struct that is defined as a member of a class is actually heap allocated. 定义为类成员的结构实际上是堆分配的。 So the argument that a struct is more efficient because of the reduced effort for garbage collection is only true in certain narrow contexts. 因此,由于减少垃圾收集的努力,结构更有效的论点仅在某些狭窄的上下文中才是正确的。

Second, any non-ValueType members of a struct are also allocated on the heap (such as strings). 其次,结构的任何非ValueType成员也在堆上分配 (例如字符串)。 So even if the struct can simply be popped off the stack, any heap objects it reference must still be garbage collected. 因此,即使结构可以简单地从堆栈中弹出,它引用的任何堆对象仍然必须进行垃圾回收。

Third, structs rarely save memory since when passed around as method arguments they have value-semantics . 第三, 结构很少会节省内存,因为当它作为方法参数传递时,它们具有值语义 This basically means that a copy of the struct is created and passed, and not a reference to the existing struct - this can't be less expensive on memory. 这基本上意味着创建并传递了结构的副本,而不是对现有结构的引用 - 这在内存上的成本也不低。 When you see other responses that say that mutable structs can be problem - it is for the reason (along with a few others) that since structs are passed by value, changes to the original struct aren't available to locations that made a copy of the struct. 当你看到其他响应表明可变结构可能有问题时 - 原因(以及其他一些结果)由于结构是按值传递的,因此对原始结构的更改不适用于制作副本的位置结构。 This can lead you to violate assumptions or expectations within a program where you may have actually desired reference semantics for the struct. 这可能会导致您违反程序中的假设或期望,在该程序中您可能实际需要结构的引用语义。


Personally, I find the pattern of creating DTO objects (whether classes or structs) to nest within your business tier objects to be one that doesn't seem to have much benefit. 就个人而言,我发现创建DTO对象(无论是类还是结构)的模式在业务层对象中嵌套是一个似乎没有多大好处的模式。 Unless you have a persistence or presentation layer that specifically leverages this pattern to pass information across tiers, I don't see much value. 除非您有专门利用此模式的持久性或表示层来跨层传递信息,否则我看不到太多价值。

Furthermore, the specific case of using a struct as the DTO object seems flawed, because it introduces unnecessary redundancy. 此外,使用结构作为DTO对象的特定情况似乎存在缺陷,因为它引入了不必要的冗余。 Since structs cannot inherit other structs, you can't express is-a relationships. 由于结构不能继承其他结构,因此无法表达is-a关系。 What do you do when you have Customer which inherits from Person. 当您拥有继承自Person的Customer时,您会怎么做。 Do you repeat all of the Person properties in the Customer struct? 您是否重复了Customer结构中的所有Person属性? Do you nest a Person struct inside a Customer struct? 您是否在Customer结构中嵌入Person结构? Neither approach is ideal. 这两种方法都不理想。 If you at least used classes, you could have Customer extend Person. 如果您至少使用过类,则可以让客户扩展Person。

It sounds pretty silly to me. 这对我来说听起来很傻。 I'm not sure how much stock I'd put in the coding advice of someone who's using tables for layout in HTML. 我不确定在HTML中使用表格进行布局的人的编码建议中有多少库存。 If this was a technique that produced significant advantages it'd be a standard practice. 如果这是一种产生显着优势的技术,那么它就是一种标准做法。 It isn't. 事实并非如此。 This is the first time I've heard of this technique. 这是我第一次听说这种技术。

Regardless of whether that strategy is more efficient, it will be more difficult to work with and I would try to avoid it. 无论该策略是否更有效,它将更难以合作,我会尽力避免它。 That being said, I doubt this would be more efficient. 话虽如此,我怀疑这会更有效率。 If it was, the compiler would probably implement it this way automatically. 如果是,编译器可能会自动以这种方式实现它。 It's generally safe to rely on the compiler to do language-level optimizations. 依靠编译器进行语言级优化通常是安全的。

Honestly, that's the first time I've heard of that approach. 老实说,这是我第一次听说这种方法。

From what I understand, structs are value types. 据我所知,结构是值类型。 In general, you want to define a struct if it's less than 16 bytes, is immutable, won't have to be boxed, and represents a single value similar to a primitive type. 通常,您希望定义一个结构,如果它小于16个字节,是不可变的,不必加箱,并且表示一个类似于基本类型的单个值。

MSDN, where Microsoft has published structure design guidelines. MSDN,Microsoft已发布结构设计指南。

Classes like your instructor is talking about will easily extend past the 16-byte rule. 像你的教师所说的类很容易超越16字节规则。 And it's hard to see a struct of this nature not encapsulating business (or, at the very least, validation) rules in the properties. 并且很难看到这种性质的结构没有封装属性中的业务(或者至少是验证)规则。 That'd be a pretty shoddy design, in my opinion. 在我看来,这是一个非常粗制滥造的设计。

The problem with this approach is that objects (instantiations of classes) have a mutable state. 这种方法的问题是对象(类的实例化)具有可变状态。 Structs in contrast should be immutable, meaning they do not have a state that can be changed. 相反,结构应该是不可变的,这意味着它们没有可以改变的状态。 In a typical application, the Business Layer heavily utilizes the changing of the state of an object (ie workflows, validation, etc.). 在典型的应用程序中,业务层大量利用对象状态的改变(即工作流程,验证等)。

The benefits he's describing do not warrant the drawbacks that this will bring on. 他所描述的好处并不能保证这会带来的弊端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM