Are protected members/fields really that bad?
现在,如果您阅读msdnforc中的命名约定,您会注意到它指出属性总是优先于公共和受保护的字段。有些人甚至告诉我,你不应该使用公共或受保护的土地。现在我同意我还没有找到一个理由,我需要一个公共领域,但保护领域真的那么糟糕吗?
我可以看到,如果您需要确保在获取/设置值时执行某些验证检查,但是在我看来,很多时候似乎只是额外的开销。我是说,假设我有一个类游戏项,其中包含basename、prefixname和suffixname字段。为什么我要承担创建属性(
Are protected members/fields really that bad?
不,是这样,更糟。
一旦一个成员比
如果现在或者将来某个时候,您的任何代码曾经依赖于某个字段某个特定的值,那么您现在必须添加有效性检查和回退逻辑,以防它不是预期的值——您使用它的每个地方。当你本来可以把它变成一个该死的财产时,这是一个巨大的浪费。
与派生类共享信息的最佳方法是只读属性:
1 | protected object MyProperty { get; } |
如果你必须让它读/写,不要。如果你真的,真的必须让它读-写,重新考虑你的设计。如果你还需要读写,向你的同事道歉,不要再这样做了:)
很多开发人员相信——并且会告诉你——这是过于严格的。的确,你可以过得很好而不必这么严格。但采用这种方法将有助于您从勉强适应到非常健壮的软件。您将花费更少的时间来修复错误。
关于性能的任何问题-不要这样。我保证在你的整个职业生涯中,你永远不会以如此快的速度编写代码,以至于瓶颈是调用堆栈本身。
好的,投票否决时间。
首先,属性永远不会影响性能(前提是它们不做太多)。其他人都这么说,我同意。
另一点是,属性很好,因为您可以在其中放置断点,以捕获获取/设置事件并找出它们的来源。
其余的争论都以这种方式困扰着我:
他们听起来像是"威望之争"。如果msdn说了,或者某个大家都喜欢的著名开发人员或作者说了,那一定是这样。
它们基于这样一个理念,即数据结构具有许多不一致的状态,必须保护它们不受漫游或放置到这些状态中。因为(在我看来)数据结构在当前的教学中被过分强调,所以它们通常需要这些保护。更可取的是最小化数据结构,使其趋向于规范化,而不具有不一致的状态。然后,如果一个类的成员被更改,那么它只是被更改,而不是被损坏。毕竟,很多好的软件都是用C语言编写的,而这并没有因为缺少保护而遭受巨大的损失。
它们基于极端的防御编码。它基于这样一个理念:你的类将在一个没有人可以信任其他代码的世界中使用,而不是欺骗你的东西。我相信有些情况下这是真的,但我从未见过。我所看到的情况是,为了绕过不需要的保护,使事情变得非常复杂,并试图保护数据结构的一致性,这些数据结构过于复杂和不规范。
关于字段与属性,我可以考虑在公共接口中优先使用属性的两个原因(受保护的也是公共的,从某种意义上说,除了您的类之外,其他人也可以看到它)。
通过公开属性,可以隐藏实现。它还允许您在不更改使用它的代码的情况下更改实现(例如,如果您决定更改数据存储在类中的方式)
许多使用反射处理类的工具只关注属性(例如,我认为一些用于序列化的库就是这样工作的)。一致地使用属性使使用这些标准.NET工具更加容易。
关于日常开支:
如果getter/setter是通常的一行代码,它只读取/设置字段的值,那么JIT应该能够内联调用,因此没有性能过剩。
当您使用自动实现的属性(C 3.0和更新版本)时,语法开销会大大减少,因此我认为这不是一个问题:
1protected int SomeProperty { get; set; }事实上,这使您可以很容易地使例如
set 受保护和get 公开,因此这比使用字段更优雅。
公共字段和/或受保护字段是不好的,因为它们可以在声明类之外进行操作,而无需验证;因此可以说它们破坏了面向对象编程的封装原则。
当您失去封装时,您就失去了声明类的契约;您不能保证该类的行为符合预期或预期。
使用属性或方法访问字段使您能够维护封装,并完成声明类的约定。
它实际上取决于您的类是数据类还是行为类。
如果将行为和数据分开,那么可以公开数据类的数据,只要它们没有行为。
如果类是行为类,那么它不应该公开任何数据。
我同意只读属性答案。但要在这里扮演魔鬼的拥护者,这真的取决于你在做什么。我很高兴地承认,我一直在和公众成员一起编写代码(我也不发表评论,不遵守指导原则,也不做任何手续)。
但当我在工作的时候,情况就不同了。