为啥类成员是私有的而属性是公共的? [复制]
Posted
技术标签:
【中文标题】为啥类成员是私有的而属性是公共的? [复制]【英文标题】:Why are class members private and properties public? [duplicate]为什么类成员是私有的而属性是公共的? [复制] 【发布时间】:2017-04-02 06:35:15 【问题描述】:在一个类中,我们将类成员声明为私有,但我们将属性定义为公共。
例如:
public class student
private int StudentId;
private string StudentName;
private string Address;
然后我们使用方法分配。
但是如果我们使用属性来获取设置定义公共喜欢。
public class student
public int StudentId get;set;;
public string StudentNameget;set;;
public string Addressget;set;;
这背后的原因是什么?
【问题讨论】:
你不要这样做因为它们是“类成员”或“属性”(顺便说一下,属性也是成员,更典型的是将它们分组静态成员和实例成员)。您通常希望封装实际的实现,因此当您访问它们时没有发生绑定逻辑的字段通常是私有的,而您可以控制写访问(谁可以写)和绑定逻辑(当您访问它们时会发生什么)的属性write) 更多时候是公开的。你想控制你的类型的公共表面,并隐藏实际的实现。 没有强制您将字段用作私有字段或将属性用作公共,但通常变量是私有的,用于类的内部使用,而属性用于外部使用,因为它们可以在以下情况下执行代码他们正在获取/设置。 此解决方案可能会清除您的情况:***.com/questions/295104/…softwareengineering.stackexchange.com/questions/133015/… 见blogs.msdn.microsoft.com/vbteam/2009/09/04/… 【参考方案1】:一个类需要控制其公共成员的行为:即控制他们做什么
想象一下,例如,如果 private string StudentName;
被设为 public
并被外部代码(外部类 student
)使用。然后你决定要添加一个验证来限制StudentName
的长度——你怎么能这样做呢?您必须在您的代码(可能还有使用此类的其他人的代码)中找到所有设置StudentName
值的实例,并在那里添加验证。
如果您使用的是 public string Student get; set;
,则不会 - 您可以轻松地将其更改为具有验证的显式属性:
private string _student;
public string Student
get return _student;
set if(value.Length <= 20) _student = value;
即使用属性可以更容易地从类内部控制类成员的行为,维护封装和抽象
【讨论】:
【参考方案2】:你是对的 - 属性通常用作公共属性。 虽然:您也可以定义这样的属性:
public int StudentId get; private set;
这将使其他类获得您的属性的值,但他们将无法更改它。
想象一下,如果您要开发一个项目,例如其中包含许多复杂控件的程序集。如果您希望用户能够读取控件中的值,因为它是经过计算的,所以您给它一个公共 getter 而一个私有 setter,因为您不希望有人操纵内部发生的事情。
【讨论】:
【参考方案3】:不完全是这样。真正的规则是:
尽可能严格地定义所有成员。
所以,如果它可以是private
,那么它就是private
。否则,如果它必须是internal
或protected
才能工作,那么它分别是internal
或protected
。否则,如果它必须是protected internal
才能工作,那么它就是protected internal
。否则,它是 public
,因为它必须是 public
才能工作(程序集之外不继承它的东西将不得不访问它。
现在,说了这么多,通常情况下,我们将拥有大部分 private
字段和大部分 public
属性。
让我们考虑一下是否有public
字段。这是有效的,会起作用,甚至在非常有限的情况下也很有用。然而它也更脆。拥有它public
可以让任何其他代码将其设置为任何值,无论多么愚蠢。没关系,因为当我们创建一个字段 public
时,我们是在说“没有愚蠢的值”。*
但是如果我们突然意识到有一些愚蠢的值,或者我们需要在每次更改字段时做一些事情,或者我们需要处理一些仅属性的数据绑定。在这里,我们将不得不将字段变成一个属性,这是一个突破性的变化;任何使用这个类的代码都必须重新编译,如果我们是唯一使用这个类的人,这没什么大不了的,但如果它在一个被其他人使用的库中。
如果它是一个属性,那么我们只需要将一个自动属性 get; set;
转换为一个具有自定义实现 get /* do stuff and return value */ set /* do stuff */
的属性。从课堂外看,似乎什么都没有改变,我们也没有破坏任何东西。
因此,如果您要创建一个字段 public
,那么在 99.99% 的情况下,您最好使用那里的属性,以防万一。
另一方面,如果我们有一个没有逻辑的private
属性,那么getter 和setter 方法不会给我们带来任何好处。不会有任何成本,但它们毫无意义。所以我们只使用一个字段。如果我们最终不得不在未来使用私有属性,那也没关系,因为唯一需要重新编译的代码就是有问题的类,而且我们无论如何都要重新编译它。
因此,我们最终会遇到几乎所有字段都是 private
并且几乎所有没有任何自定义逻辑的属性都是 protected
或 public
的情况。
*或者它是 private
或 internal
类,我们从外部承诺不会将其设置为愚蠢的东西,但如果可以的话,最好执行承诺而不是做出承诺。
【讨论】:
【参考方案4】:不直接设置字段,而是通过属性,遵循封装的面向对象原则。这包括一个类是其对象包含的数据的老板。一个类应该始终控制对其数据的访问(无论是读取还是写入)。有时这意味着他们需要执行额外的步骤来确保数据的一致性。但即使他们不这样做,也应该对调用者隐藏不应该这样做的事实,因为这不关他们的事(关注点分离)。因此,简单的规则:对象数据没有快捷方式。如果你想得到一些,你必须让班级给你。在 C# 中,这就是属性的用途。
【讨论】:
【参考方案5】:使用属性并将其公开的背后有多种原因
将类字段标记为公开和公开是有风险的,因为您将 无法控制分配和返回的内容。
想要在值更改时闯入调试器?只需在 setter 中添加断点即可。
想要记录所有访问?只需将日志记录添加到 getter 即可。 属性用于数据绑定;字段不是。
为私有成员添加验证(比如值不能设置为负)。
在 null、空或零的情况下返回一些默认值。
属性可以声明为读/写、只读或只写。
其他好处,反射和数据绑定。
【讨论】:
【参考方案6】:在这个最简单的情况下没有特殊原因。但是如果你在开发中走得更远 - 它会变得非常清楚:你需要从实现中抽象出来并分离出一个接口,例如只是为了在单元测试中模拟学生。所以,从长远来看,你宁愿需要接口和属性,从一开始就以可模拟和可测试的方式编写它只是一种习惯
public interface IStudent
int StudentId get; set;
string StudentName get; set;
string Address get; set;
public class Student : IStudent
public int StudentId get; set;
public string StudentName get; set;
public string Address get; set;
【讨论】:
以上是关于为啥类成员是私有的而属性是公共的? [复制]的主要内容,如果未能解决你的问题,请参考以下文章