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

rya*_*zec 31 c# performance coding-style access-levels

现在,如果您阅读MSDN for C#中的命名约定,您会注意到它声明属性始终优先于public和protected字段.有些人甚至告诉我,你永远不应该使用公共或受保护的领域.现在我同意我还没有找到一个理由,我需要有一个公共领域,但受保护的领域真的那么糟糕?

我可以看到它,如果您需要确保在获取/设置值时执行某些验证检查,但是在我看来,很多时候它似乎只是额外的开销.我的意思是说我有一个类GameItem,其中包含baseName,prefixName和suffixName的字段.我为什么要承担创建属性(C#)或访问器方法的开销以及我将要发生的性能损失(如果我对应用程序中的每个字段执行此操作,我相信它会稍微增加一点,尤其是某些语言PHP或某些具有性能的应用程序是否像游戏一样至关重要?

Rex*_*x M 80

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

不,他们的方式更糟糕了.

一旦成员更容易访问private,您就会向其他类提供有关该成员如何行为的保证.由于一个字段是完全不受控制的,因此将它"放在野外"会打开你的类和类,这些类和类会从你的类中继承或与之交互,从而导致更高的bug风险.没有办法知道一个字段何时发生变化,无法控制改变它的人或者是什么.

如果现在,或者在将来某个时候,您的任何代码都依赖于某个特定值的字段,您现在必须添加有效性检查和回退逻辑,以防它不是预期值 - 您使用它的每个地方.当你只是把它变成一个该死的财产时,这是一大笔浪费的努力;)

与派生类共享信息的最佳方法是只读属性:

protected object MyProperty { get; }
Run Code Online (Sandbox Code Playgroud)

如果你绝对必须让它读/写,不要.如果你真的,真的必须让它读写,重新考虑你的设计.如果您仍然需要它进行读写,请向同事道歉并且不要再这样做:)

许多开发人员相信 - 并且会告诉你 - 这是非常严格的.而且这是真的,你可以通过获得就好而不这种严格.但是采用这种方法可以帮助您从刚刚过去到非常强大的软件.你将花费更少的时间来修复bug.

关于对性能的任何担忧 - 不要.我保证在你的整个职业生涯中,你永远不会编写如此快速的代码,以至于瓶颈就是调用堆栈本身.

  • +1,如果可以的话,更多.一旦你成为一个非私人的成员,你就会永远和永远地坚持下去.这是你的公共界面. (10认同)
  • @Daniel 使属性可写会增加复杂性的数量级。在现实世界中,“每个”类都是不可变的绝对是不现实的,但如果大多数类都是不可变的,那么编写无错误的代码就会变得非常容易。我曾经得到过这样的启示,我希望能帮助其他人得到它。 (2认同)
  • @ryanzec 你成功了!消费者应该只能在初始化时设置对象的状态(通过构造函数)。一旦对象产生了生命,它就应该在内部对其自己的状态生命周期负责。允许消费者影响国家会增加不必要的复杂性和风险。 (2认同)

Mik*_*vey 28

好吧,请关注时间.

  • 首先,属性永远不会损害性能(前提是它们没有做太多).这就是其他人所说的,我同意.

  • 另一点是,属性很好,你可以在其中放置断点来捕获获取/设置事件并找出它们的来源.

其余的论点以这种方式困扰着我:

  • 他们听起来像"声望的争论".如果MSDN说它,或者每个人都喜欢的着名开发者或作者说出来,那一定是这样.

  • 它们基于数据结构具有许多不一致状态的想法,并且必须防止流浪或被置于这些状态.由于(在我看来)数据结构在当前教学中过分强调,因此通常他们确实需要这些保护.更优选的是使数据结构最小化,以使其趋于标准化并且不具有不一致的状态.然后,如果一个类的成员被更改,它只是被改变,而不是被损坏.毕竟,不知何故,许多优秀的软件都是用C编写的,并且没有因缺乏保护而遭受大量损失.

  • 它们基于极端的防御性编码.它基于这样一种想法,即您的类将被用于一个世界,在这个世界中,没有其他人的代码可以信任,不会使您的东西蠢蠢欲动.我确信有些情况确实存在,但从未见过它们.我看到的是这样的情况,即在没有必要的情况下保护事物变得非常复杂,并且试图保护数据结构的一致性,这些数据结构非常复杂和非标准化.

  • 很好的一点.我只想提出一个想法:如果你在一个超过1的团队中工作,那么你的代码就是疯狂的.任何未明确强制执行的合同都容易受到误解.它通过消除歧义和通过设计强制执行信息流,为您的队友提供优质服务,并减少每个人的努力. (7认同)
  • Python 本质上没有私有方法,更不用说受保护的方法了,而且在实践中这也没什么大不了的。 (3认同)
  • 也许大多数人只是抽象地相信它,但既然我已经开始生活,并为我的团队制定政策,生活变得更加愉快.输出上升,错误率下降,幸福感上升.毫无疑问,改变工作方式是一个艰难的攀登山.IMO它不仅仅值得. (3认同)

Tom*_*cek 6

关于字段与属性,我可以想到在公共接口中优选属性的两个原因(受保护的也是公共的,因为除了你的类以外的其他人可以看到它).

  • 公开属性为您提供了隐藏实现的方法.它还允许您更改实现而不更改使用它的代码(例如,如果您决定更改数据存储在类中的方式)

  • 许多使用反射的类工作的工具只关注属性(例如,我认为一些用于序列化的库以这种方式工作).使用属性可以更容易地使用这些标准.NET工具.

关于间接费用:

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

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

    protected int SomeProperty { get; set; }
    
    Run Code Online (Sandbox Code Playgroud)

    事实上,这使您可以非常轻松地制作set受保护和get公开的示例,因此这比使用字段更加优雅.


Håv*_*d S 5

公共和/或受保护的字段很糟糕,因为它们可以在声明类之外进行操作而无需验证; 因此可以说它们打破了面向对象编程的封装原则.

当你失去封装时,你就失去了宣告类的合同; 您无法保证该类的行为符合预期或预期.

使用属性或方法访问该字段使您能够维护封装,并履行声明类的合同.