现在,如果您阅读MSDN for C#中的命名约定,您会注意到它声明属性始终优先于public和protected字段。有些人甚至告诉我,你永远不应该使用公共或受保护的领域。现在我同意我还没有找到一个理由,我需要有一个公共领域但受保护的领域真的那么糟糕?
如果您需要确保在获取/设置值时执行某些验证检查,我可以看到它,但是在我看来,很多时候它似乎只是额外的开销。我的意思是说我有一个类GameItem,其中包含baseName,prefixName和suffixName的字段。为什么我要承担创建属性(C#
)或访问器方法的开销以及我会发生的性能损失(如果我对应用程序中的每个字段执行此操作,我相信它会增加特别是在PHP
等特定语言中,或者某些具有性能的应用程序如游戏一样重要?
答案 0 :(得分:78)
受保护的成员/字段真的那么糟糕吗?
否。他们的方式更糟糕。
只要成员比private
更容易访问,您就会向其他类提供有关该成员行为方式的保证。由于一个字段是完全不受控制的,因此将它“放在野外”会打开你的类和类,这些类和类会从你的类中继承或与之交互,从而导致更高的bug风险。没有办法知道某个字段何时发生变化,无法控制改变它的人或者是什么。
如果现在,或者在将来的某个时候,你的任何代码都依赖于某个特定值的字段,你现在必须添加有效性检查和回退逻辑,以防它不是预期值 - 你使用它的每个地方。当你只是把它变成一个该死的财产时,这是一大笔浪费的努力;)
最佳与派生类共享信息的方式是只读属性:
protected object MyProperty { get; }
如果您绝对 使其可读/写,请不要。如果你真的,真的必须让它读写,重新考虑你的设计。如果你仍然需要它进行读写,请向你的同事道歉,不要再这样做了。)
许多开发人员相信 - 并且会告诉你 - 这是非常严格的。而且你可以通过获得正确而不是这么严格。但是采用这种方法可以帮助您从刚刚过去到非常强大的软件。你将花费更少的时间来修复bug。
关于对表现的任何担忧 - 不要。我保证在你的整个职业生涯中,你永远不会编写如此快速的代码,以至于瓶颈就是调用堆栈本身。
答案 1 :(得分:26)
好的,请关注时间。
首先,属性永远不会影响性能(前提是它们没有做太多事情)。这就是其他人所说的,我同意。
另一点是,属性很好,因为你可以在它们中放置断点来捕获获取/设置事件并找出它们的来源。
其余论据以这种方式困扰我:
他们听起来像是“声望的争论”。如果MSDN说出来,或者每个人都喜欢的着名开发者或作者说出来,必须。
它们基于数据结构具有许多不一致状态的想法,并且必须防止流浪或被置于这些状态。由于(在我看来)数据结构在当前教学中过于强调,因此通常他们做需要这些保护。更优选的是最小化数据结构以使其趋于标准化并且不具有不一致的状态。然后,如果一个类的成员被更改,它只是被改变,而不是被损坏。毕竟,不知何故,许多优秀的软件用C编写,并且没有因缺乏保护而大量受损。
它们基于极端的防御性编码。它基于这样一种想法,即您的类将被用于一个世界,在这个世界中,没有其他人的代码可以信任,不会使您的东西蠢蠢欲动。我确信在某些情况下这是真的,但我从未见过他们。我所看到的看到的情况是,为了解决没有必要的保护而使事情变得非常复杂,并试图保护数据结构的一致性,这些数据结构过于复杂和不规范化
答案 2 :(得分:6)
关于字段与属性,我可以想到在公共界面中偏好属性的两个原因(受保护的也是公共的,除了你的类以外的其他人可以看到它)。
公开属性为您提供了隐藏实现的方法。它还允许您更改实现而不更改使用它的代码(例如,如果您决定更改数据存储在类中的方式)
许多使用反射的类工作的工具只关注属性(例如,我认为某些用于序列化的库以这种方式工作)。使用这些属性可以更容易地使用这些标准的.NET工具。
关于间接费用:
如果getter / setter是通常的一行代码,它只是读取/设置字段的值,那么JIT应该能够内联调用,因此没有性能改变。
当您使用自动实现的属性(C#3.0和更新版本)时,语法开销会大大减少,所以我不认为这是一个问题:
protected int SomeProperty { get; set; }
事实上,这使您可以非常轻松地制作例如set
受保护和get
公开,因此这比使用字段更优雅。
答案 3 :(得分:5)
公共和/或受保护的字段很糟糕,因为它们可以在声明类之外进行操作而无需验证;因此可以说它们打破了面向对象程序设计的封装原则。
当你失去封装时,你就失去了申报类的合同;您不能保证该类的行为符合预期或预期。
使用属性或方法访问该字段使您能够维护封装,并履行声明类的合同。
答案 4 :(得分:0)
我同意只读属性的答案。但是要在这里扮演魔鬼的拥护者,这实际上取决于你在做什么。我很乐意承认我一直在与公众成员一起编写代码(我也不会发表评论,遵循指导方针或任何手续)。
但是,当我在工作时,这是一个不同的故事。
答案 5 :(得分:0)
实际上,这取决于您的类是数据类还是行为类。
如果您keep your behaviour and data separate,只要它们没有行为,就可以公开数据类的数据。
如果类是行为类,则不应公开任何数据。