简体   繁体   English

受保护的成员/领域真的那么糟糕吗?

[英]Are protected members/fields really that bad?

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. 现在,如果您阅读MSDN for C#中的命名约定,您会注意到它声明属性始终优先于public和protected字段。 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. 我的意思是说我有一个类GameItem,其中包含baseName,prefixName和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)? 为什么我要承担创建属性( C# )或访问器方法的开销以及我会发生的性能损失(如果我对应用程序中的每个字段执行此操作,我相信它会稍微增加一点点,特别是在某些语言如PHP或某些具有性能的应用程序如游戏一样至关重要?

Are protected members/fields really that bad? 受保护的成员/领域真的那么糟糕吗?

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. 只要成员比private更容易访问,您就可以向其他类保证该成员的行为方式。 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. 由于一个字段是完全不受控制的,因此将它“放在野外”会打开你的类和类,这些类和类会从你的类中继承或与之交互,从而导致更高的bug风险。 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 : 与派生类共享信息的最佳方法是只读属性

protected object MyProperty { get; }

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. 你将花费更少的时间来修复bug。

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. 我保证在你的整个职业生涯中,你永远不会编写如此快速的代码,以至于瓶颈就是调用堆栈本身。

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. 如果MSDN说它,或者每个人都喜欢的着名开发者或作者说出来,那一定是这样。

  • 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. 毕竟,不知何故,许多优秀的软件都是用C编写的,并且没有因缺乏保护而遭受大量损失。

  • 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. 看到的是这样的情况,即在没有必要的情况下保护事物变得非常复杂,并且试图保护数据结构的一致性,这些数据结构非常复杂和非标准化。

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 (eg 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. 使用属性可以更容易地使用这些标准.NET工具。

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. 如果getter / setter是通常只读取/设置字段值的一行代码,那么JIT应该能够内联调用,因此没有性能改变。

  • 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: 当您使用自动实现的属性(C#3.0和更新版本)时,语法开销会大大减少,所以我不认为这是一个问题:

     protected int SomeProperty { get; set; } 

    In fact, this allows you to make for example set protected and get public very easily, so this can be even more elegant than using fields. 事实上,这可以让你做,例如set保护,并get公众很容易,所以这可能比使用领域更优雅。

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. 使用属性或方法访问该字段使您能够维护封装,并履行声明类的合同。

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. 但是,当我在工作时,这是一个不同的故事。

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. 如果该类是行为类,则它不应公开任何数据。

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

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