我应该使用公共属性和私有字段还是公共字段来存储数据?
Posted
技术标签:
【中文标题】我应该使用公共属性和私有字段还是公共字段来存储数据?【英文标题】:Should I use public properties and private fields or public fields for data? 【发布时间】:2010-11-19 15:20:25 【问题描述】:在我看到的大部分代码中(在 SO,thecodeproject.com 上,我倾向于在我自己的代码中执行此操作),我看到为类包含的每个私有字段创建公共属性,即使它们是get; set;
的最基本类型如:
private int myInt;
public int MyInt
get return myInt;
set myInt = value
我的问题是:这与:
public int MyInt;
如果我们应该使用属性而不是公共字段,为什么我们应该在这种特定情况下使用它们? (我不是在谈论更复杂的示例,其中 getter 和 setter 实际上做了一些特殊的事情,或者只有一个 get 或 set(仅读/写),而不仅仅是返回/设置私有字段的值)。它似乎没有添加任何额外的封装,只是在 IntelliSense 中给出了一个漂亮的图标,并放在类图中的特殊部分!
【问题讨论】:
这真的不是复制品吗? 很难相信这个问题直到现在都没有在这里问过! 是的,我认为我做到了。等我追捕它... 前一天问过:Property(with no extra processing) vs public field :) 【参考方案1】:看这篇文章http://blog.codinghorror.com/properties-vs-public-variables/
具体来说
反射对变量和属性的工作方式不同,因此如果您依赖反射,则可以更轻松地使用所有属性。 您不能对变量进行数据绑定。 将变量更改为属性是一项重大更改。【讨论】:
使用属性比使用字段更可取,因为您可以更改 get 和 set 块中的语句,而无需更改依赖于属性的类。【参考方案2】:有很多原因。
主要是:
设置变量后,您可以执行一些其他功能 您可以阻止设置并仅提供获取 某些“事物”仅适用于属性(例如 DataBinding) 您可以隐藏属性的实现 [也许它是一个 ViewState 变量,在 ASP.NET 中)。【讨论】:
【参考方案3】:嗯,它确实有所作为。公共数据可以在对象实例不知道的情况下更改。使用 getter 和 setter 时,对象总是知道发生了变化。
请记住,封装数据只是迈向更好的结构化设计的第一步,它本身并不是最终目标。
【讨论】:
【参考方案4】:关键是 - 如果您想确保每次引用 myInt
时都会发生一些特殊情况(写入日志文件,将其更改为 42 等),该怎么办?如果没有 getter 和 setter,你就无法做到这一点。有时,明智的做法是针对您可能需要的内容进行编程,而不是您现在需要的内容。
【讨论】:
对于某些类型,这样的场景是现实的。对于其他人,他们不是。你能想到Point
的未来版本在属性 getter 或 setter 中可能有用的任何事情吗?如果Point
是一个具有virtual 属性的类,那么未来的派生类可能能够添加有用的行为,但是由于特定的Point
实例不知道它们的用途,并且是预计会接受 X
和 Y
的任何 Int32
值,我想不出未来的实现可能会添加什么。【参考方案5】:
三个原因:
-
您不能像属性一样覆盖子类中的字段。
您最终可能需要更复杂的 getter 或 setter,但如果它是一个字段,更改它会破坏 API。
公约。这就是它的完成方式。
我确信还有更多我没有想到的原因。
在 .Net 3.x 中,您可以使用如下自动属性:
public int Age get; set;
而不是像这样自己声明私有字段的老式方法:
private int age;
public int Age
get return age;
set age = value;
这使得它像创建一个字段一样简单,但没有重大更改问题(除其他外)。
【讨论】:
=1:你从哪里得到不能序列化的字段? "你最终可能需要一个更复杂的 getter 或 setter,但如果它是一个字段,更改它会破坏 API。"并不真地。您可以安全地从:public int Joe;私有 int _joe; public int Joe get //do something set //do something 您可能需要更改很多内部引用,但这不会破坏您的 API。 @John Saunders 这就是我读到的……这不是真的吗?这是真的吗? @Russel Steen 好的,也许不会破坏 API,但您必须重新编译 @Russell Steen - 当然这是一个重大变化。仅仅因为它在 C# 中看起来相同并不意味着它是相同。您将字段访问更改为方法调用,这是完全不同的,任何调用代码都需要重新编译。【参考方案6】:实际上,如果您使用 Silverlight,您会意识到无法将字段设置为静态资源,因此您必须使用属性(甚至访问 const
)。
当我尝试联合我在 Composite Guidance (PRISM) 中使用的区域名称时,我意识到这一点。
不过,这只是语言限制,除了 static
/const
字段外,我总是使用属性。
【讨论】:
【参考方案7】:这个想法是您不应该意外/无意地更改外部类私有字段的值。 当您使用 get 和 set 时,这意味着您有意且有意地更改了类私有字段。
【讨论】:
【参考方案8】:当您创建私有字段 name 和一个简单的公共属性 Name 时,它实际上获取和设置 name 字段值
public string Name
get return name;
并且你在你的类之外的任何地方都使用这个属性,有一天你决定这个类的 Name 属性实际上将引用 lastName 字段(或者你想要要返回字符串“我的名字:”+name),您只需更改属性内的代码:
public string Name
get return lastName; //return "My name: "+name;
如果您在外部代码中的任何地方都使用公共字段 name,那么您必须在使用它的任何地方将 name 更改为 lastName。
【讨论】:
【参考方案9】:将值设置为私有字段只会更改该字段,但将它们放在属性中您可以处理其他参数,例如,您可以在设置值后调用方法
私人字符串_email; 公共字符串电子邮件 得到 返回这个._email; 放 this._email = 价值; 替换列表(); //**【讨论】:
好的,但他不需要做任何其他事情,只需返回_email。那么,usng 属性的原因是什么?原因就在我的答案中 - 以备将来使用。【参考方案10】:这...取决于?
我总是使用 getter 和 setter,因为他们创建了这个快捷方式:
公共 int Foo 获取;放;
在编译时它被翻译。现在你不能对它感兴趣,但它就在那里,如果你需要花哨,你以后再拼出来。
无论是公开的、私有的还是受保护的……这完全取决于您希望谁能够调整数据。我们经常使用继承,这对我们来说是一种非常常用的方法,因此只有孩子才能编辑某些属性。
protected _foo;
public Foo
get return _foo;
//lack of set intentional.
【讨论】:
【参考方案11】:我不敢相信有 11 个答案,没有人这么说:
并非所有私有字段都应作为公共属性公开。您当然应该对任何需要非私有的东西使用属性,但您应该尽可能多地保持类的私有。
【讨论】:
重读这个问题 - 在这种情况下,我需要从课堂外访问这些私有字段。当然,您不会公开每个字段或给每个字段一个属性! 实际上,这个问题并没有说明您需要什么,只说明了您所看到的为每个私有字段创建的公共属性。如果您有需要公共访问的字段,那么它们不是私有字段,并且与您提出的问题不匹配。请编辑问题以明确您的代码中包含的内容,而不是您在“SO,thecodeproject.com”上看到的示例【参考方案12】:你必须在以下情况下使用属性:
-
当您需要将属性中的数据序列化为某种格式时。
当您需要覆盖派生类中的属性时。
当您使用某些逻辑实现 get 和 set 方法时。例如,当您实现单例模式时。
当您从接口派生时,在其中声明了属性。
当您遇到与反射相关的具体问题时。
【讨论】:
为什么认为字段不能序列化?【参考方案13】:简单来说,您的问题的答案是访问修饰符,即公共和私有。
如果你使用:
public int myInt;
public int MyInt
get return myInt;
set myInt = value
那么在要修改的项目中,MyInt 属性和 myInt 变量都可用。 意思是,如果你的类假设 A 被类假设 B 继承, 那么 myInt 和 MyInt 都可以修改并且不能应用检查。 假设如果某些特定条件通过,您希望 myInt 值可以在派生类中设置。
这只能通过将字段设为私有并将属性设为公共来实现。 这样只有属性可用,并且可以根据它设置条件。
【讨论】:
以上是关于我应该使用公共属性和私有字段还是公共字段来存储数据?的主要内容,如果未能解决你的问题,请参考以下文章