受保护的成员/字段真的那么糟糕吗?
现在,如果您阅读 MSDN 中 C# 的命名约定,您会注意到它指出属性始终优先于公共字段和受保护字段。有些人甚至告诉我,你永远不应该使用公共或受保护的领域。现在我同意我还没有找到需要拥有公共领域的理由,但受保护的领域真的那么糟糕吗?
如果您需要确保在获取/设置值时执行某些验证检查,我可以看到它,但在我看来,很多时候这似乎只是额外的开销。我的意思是,假设我有一个 GameItem 类,其中包含 baseName、prefixName 和 suffixName 字段。为什么我应该承担创建属性 (C#
) 或访问器方法的开销以及可能发生的性能损失(如果我对应用程序中的每个字段都这样做,我确信它会加起来少一点,特别是在某些语言(如 PHP)或某些性能至关重要的应用程序(如游戏)中?
Now if you read the naming conventions in the MSDN for C# you will notice that it states that properties are always preferred over public and protected fields. I have even been told by some people that you should never use public or protected fields. Now I will agree I have yet to find a reason in which I need to have a public field but are protected fields really that bad?
I can see it if you need to make sure that certain validation checks are performed when getting/setting the value however a lot of the time it seems like just extra overhead in my opinion. I mean lets say I have a class GameItem with fields for baseName, prefixName, and suffixName. Why should I take the overhead of both creating the properties (C#
) or accessor methods and the performance hit I would occur (if I do this for every single field in an application, I am sure that it would adds up at less a little especially in certain languages like PHP
or certain applications with performance is critical like games)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
不。它们的情况非常非常糟糕。
一旦某个成员比
private
更容易访问,您就可以向其他类保证该成员的行为方式。由于字段完全不受控制,因此将其“放在野外”会使您的类以及从您的类继承或与您的类交互的类面临更高的错误风险。无法知道字段何时发生变化,也无法控制谁或什么改变了它。如果现在或将来的某个时候,您的任何代码曾经依赖于某个字段的某个值,那么您现在必须添加有效性检查和回退逻辑,以防它不是预期值 - 您使用它的每个地方。当您可以将其变成一个该死的属性时,这是浪费大量精力;)
与派生类共享信息的最佳方法是只读属性 :
如果您绝对必须使其读/写,请不要这样做。如果您确实必须使其可读,请重新考虑您的设计。如果您仍然需要它是读写的,请向您的同事道歉,并且不要再这样做了:)
许多开发人员相信 - 并且会告诉您 - 这过于严格。确实,不用这么严格也可以过得很好。但采用这种方法将帮助您从勉强过得去的软件变成非常强大的软件。您将花费更少的时间来修复错误。
至于对性能的任何担忧——不要担心。我保证,在你的整个职业生涯中,你永远不会写代码太快,以至于瓶颈是调用堆栈本身。
No. They are way, way worse.
As soon as a member is more accessible than
private
, you are making guarantees to other classes about how that member will behave. Since a field is totally uncontrolled, putting it "out in the wild" opens your class and classes that inherit from or interact with your class to higher bug risk. There is no way to know when a field changes, no way to control who or what changes it.If now, or at some point in the future, any of your code ever depends on a field some certain value, you now have to add validity checks and fallback logic in case it's not the expected value - every place you use it. That's a huge amount of wasted effort when you could've just made it a damn property instead ;)
The best way to share information with deriving classes is the read-only property:
If you absolutely have to make it read/write, don't. If you really, really have to make it read-write, rethink your design. If you still need it to be read-write, apologize to your colleagues and don't do it again :)
A lot of developers believe - and will tell you - that this is overly strict. And it's true that you can get by just fine without being this strict. But taking this approach will help you go from just getting by to remarkably robust software. You'll spend far less time fixing bugs.
And regarding any concerns about performance - don't. I guarantee you will never, in your entire career, write code so fast that the bottleneck is the call stack itself.
好的,投反对票时间到了。
首先,属性永远不会损害性能(只要它们作用不大)。其他人都是这么说的,我也同意。
另一点是属性的好处在于您可以在其中放置断点来捕获获取/设置事件并找出它们来自哪里。
其余的论点以这种方式困扰着我:
它们听起来像是“声望论”。如果 MSDN 这么说,或者某个人人都喜欢的著名开发者或作者这么说,那么一定就是这样。
它们基于这样的想法:数据结构具有许多不一致的状态,并且必须防止徘徊或被置于这些状态中。由于(在我看来)数据结构在当前的教学中被过分强调,因此通常它们确实需要这些保护。更可取的是最小化数据结构,以便它趋于规范化并且不具有不一致的状态。那么,如果类的成员被更改,它只是被更改,而不是被损坏。毕竟,不知何故,许多优秀的软件都是用 C 语言编写的,并且并没有因缺乏保护而受到严重影响。
它们基于极端的防御性编码。它基于这样的想法:您的类将在一个没有人可以相信其他人的代码不会破坏您的东西的世界中使用。我确信在某些情况下这是真的,但我从未见过它们。我所看到的情况是,事情变得非常复杂,以绕过不需要的保护,并试图保护过于复杂和非规范化的数据结构的一致性.
OK, downvote time.
First of all, properties will never hurt performance (provided they don't do much). That's what everyone else says, and I agree.
Another point is that properties are good in that you can place breakpoints in them to capture getting/setting events and find out where they come from.
The rest of the arguments bother me in this way:
They sound like "argument by prestige". If MSDN says it, or some famous developer or author whom everybody likes says it, it must be so.
They are based on the idea that data structures have lots of inconsistent states, and must be protected against wandering or being placed into those states. Since (it seems to me) data structures are way over-emphasized in current teaching, then typically they do need those protections. Far more preferable is to minimize data structure so that it tends to be normalized and not to have inconsistent states. Then, if a member of a class is changed, it is simply changed, rather than damaged. After all, somehow lots of good software was/is written in C, and that didn't suffer massively from lack of protections.
They are based on defensive coding carried to extremes. It is based on the idea that your classes will be used in a world where nobody else's code can be trusted not to goose your stuff. I'm sure there are situations where this is true, but I've never seen them. What I have seen is situations where things were made horribly complicated to get around protections for which there was no need, and to try to guard the consistency of data structures that were horribly over-complicated and un-normalized.
关于字段与属性,我可以想到在公共接口中更喜欢属性的两个原因(受保护的属性也是公共的,因为除了您的类之外的其他人都可以看到它)。
公开属性为您提供了一种隐藏实现的方法。它还允许您在不更改使用它的代码的情况下更改实现(例如,如果您决定更改数据在类中存储的方式)
许多使用反射处理类的工具仅关注属性(例如,我认为一些序列化库是这样工作的)。一致地使用属性可以更轻松地使用这些标准 .NET 工具。
关于开销:
如果 getter/setter 是通常的一行代码,仅读取/设置字段的值,那么 JIT 应该能够内联调用,因此不会出现性能过高。
当您使用自动实现的属性(C# 3.0 及更高版本)时,语法开销会大大减少,因此我认为这不是一个问题:
事实上,这使您可以非常轻松地进行
set
protected 和get
public 等操作,因此这比使用字段更加优雅。Regarding fields vs. properties, I can think of two reasons for prefering properties in the public interface (protected is also public in the sense that someone else than just your class can see it).
Exposing properties gives you a way to hide the implementation. It also allows you to change the implementation without changing the code that uses it (e.g. if you decide to change the way data are stored in the class)
Many tools that work with classes using reflection only focus on properties (for example, I think that some libraries for serialization work this way). Using properties consistently makes it easier to use these standard .NET tools.
Regarding overheads:
If the getter/setter is the usual one line piece of code that simply reads/sets the value of a field, then the JIT should be able to inline the call, so there is no performance overhad.
Syntactical overhead is largely reduced when you're using automatically implemented properties (C# 3.0 and newer), so I don't think this is an issue:
In fact, this allows you to make for example
set
protected andget
public very easily, so this can be even more elegant than using fields.公共和/或受保护的字段是不好的,因为它们可以在没有验证的情况下从声明类的外部进行操作;因此可以说它们打破了面向对象编程的封装原则。
当你失去封装性时,你就失去了声明类的契约;您不能保证该类的行为符合预期或预期。
使用属性或方法访问字段使您能够维护封装并履行声明类的契约。
Public and/or protected fields are bad because they can be manipulated from outside the declaring class without validation; thus they can be said to break the encapsulation principle of object oriented programming.
When you lose encapsulation, you lose the contract of the declaring class; you cannot guarantee that the class behaves as intended or expected.
Using a property or a method to access the field enables you to maintain encapsulation, and fulfill the contract of the declaring class.
这实际上取决于您的类是数据类还是行为类。
如果将行为和数据分开,那么公开数据类的数据就可以了,只要它们没有行为即可。
如果该类是行为类,那么它不应该公开任何数据。
It actually depends on if your class is a data class or a behaviour class.
If you keep your behaviour and data separate, it is fine to expose the data of your data classes, as long as they have no behaviour.
If the class is a behaviour class, then it should not expose any data.
我同意只读属性的答案。但要在这里唱反调,这实际上取决于你在做什么。我很高兴承认我一直与公共成员一起编写代码(我也不发表评论、遵循指南或任何形式)。
但当我在工作时,情况就不同了。
I agree with the read-only property answer. But to play devil's advocate here, it really depends on what you're doing. I'll be happy to admit i write code with public members all the time (i also don't comment, follow guidelines, or any of the formalities).
But when i'm at work that's a different story.