2009-08-14 67 views
50

在我看到的大部分代码中(在SO上,codeproject.com和我倾向于在我自己的代码中执行此操作),我已经看到为类的每个单独私有字段创建的公共属性,即使它们是像最基本类型的get; set;我应该使用公共财产和私人领域或公共领域的数据?

private int myInt; 
public int MyInt 
{ 
    get { return myInt; } 
    set { myInt = value } 
} 

我的问题是:它如何从不同:

public int MyInt; 

,如果我们要使用属性,而不是公共领域,为什么我们要在这个特定使用它们案件? (我不是在谈论更复杂的例子,其中getter和setter实际上做了一些特殊的事情,或者只有一个get或set(只读/写)而不是返回/设置私有字段的值。它似乎没有添加任何额外的封装,只在IntelliSense中给出一个漂亮的图标,并放置在类图的特殊部分!

+0

这真的不是重复的吗? – 2009-08-14 12:49:09

+0

很难相信这个问题在这里没有被问到,直到现在! – 2009-12-23 08:32:59

+0

这是,我认为它。当我追捕它时,请继续...... – RCIX 2010-02-03 09:05:37

回答

30

请参阅本文http://blog.codinghorror.com/properties-vs-public-variables/

具体

  • 思考的工作方式不同的变量与属性,所以如果依靠反射,它更容易使用的所有属性。
  • 您无法对变量进行数据绑定。
  • 将变量更改为属性是一项重大改变。
+1

使用属性优于使用字段,因为 您可以更改get和set块中的语句,而无需更改依赖于属性的类。 – user2211290 2016-08-23 10:46:51

0

原因有很多。

主要是:

  • 你可以做一些其他的功能,当变量被设置
  • 您可以防止设置,并提供了获得
  • 的性能(数据绑定一些“东西”只工作,例如)
  • 您可以隐藏该属性的实现[也许它是一个ViewState变量,在ASP.NET中)。
5

那么它确实有所作为。公共数据可以在对象实例不知道它的情况下进行更改。使用getter和setter对象总是会意识到已经做出更改。请记住,封装数据只是实现更好结构化设计的第一步,它本身并不是最终目标。

0

问题是 - 如果你想要确保每次引用myInt时发生了特殊情况(写入日志文件,将其更改为42等),该怎么办?如果没有获得者和制定者,你就无法做到这一点。有时候编制你可能需要的东西是明智的,而不是你现在需要的东西。

+0

对于某些类型,这种情况是现实的。对于其他人,他们不是。你能想到任何未来版本的'Point'可能在属性获取器或设置器中有用吗?如果'Point'是一个具有* virtual *属性的类,未来的派生类可能会添加有用的行为,但是由于特定的'Point'实例不知道它们被用于什么,并且预期会接受任何' “X”和“Y”的Int32'值,我想不出任何未来的实现可能会增加。 – supercat 2013-06-04 21:07:22

19

理由三:

  1. 喜欢你可以将属性不能覆盖领域中的子类。
  2. 您可能最终需要更复杂的getter或setter,但如果它是一个字段,则更改它会破坏API。
  3. 公约。这就是它完成的方式。

我敢肯定还有更多的原因,我只是没有想到。

在.net 3.x中,你可以使用自动属性是这样的:

public int Age { get; set; } 

,而不是老派的方式与自己宣布你的私人领域是这样的:

private int age; 

public int Age 
{ 
    get { return age; } 
    set { age = value; } 
} 

这使得就像创建一个字段一样简单,但没有突破性变化问题(等等)。

+0

= 1:你在哪里得到的字段不能被序列化? – 2009-08-14 12:38:08

+1

“您最终可能需要更复杂的getter或setter,但如果它是一个字段,更改它会破坏API。” 不是。 您可以安全地从:public int Joe; 至 private int _joe; 公众诠释乔 { 获得{//做一些事情} 集合{//做一些事情}} 您可能需要改变很多内部参考的,但是,这并不破坏你的API。 – 2009-08-14 12:39:41

+0

@John Saunders这就是我读过的......这是不是真的?它是真的吗? – 2009-08-14 12:42:28

0

实际上,如果您使用的是Silverlight,您会意识到无法将字段设置为静态资源,因此您必须使用属性(即使访问const)。

我意识到,当我试图联合在复合制导(PRISM)中使用的区域名称。

但是,这只是一种语言限制,除了static/const字段,我也会使用属性。

0

这个想法是你不应该意外/无意中改变一个班级私人领域的价值。 当你使用get和set时,这意味着你有意和有意地改变了类私有域。

6

当您创建私有字段和简单的公共财产名称实际获取和设置名称字段值

public string Name 
{ 
    get { return name; } 
} 

,你到处使用这个属性类,有一天外面你决定名称这个类的属性实际上是指姓氏字段(或者你想返回一个字符串“My name:”+ name),你只需要在里面修改代码属性:

public string Name 
{ 
    get { return lastName; //return "My name: "+name; } 
} 

如果你在外面的代码中使用公共领域无处不在,那么你就必须改变lastName的无处不在,你使用它。

0

设置一个值转换成私有字段只改变了场,但使他们的财产,你可以处理其它参数,例如,你可以设置一个值

 
private string _email; 
public string Email 
{ 
    get 
    { 
     return this._email; 
    } 
    set 
    { 
     this._email = value; 
     ReplaceList(); //** 
    } 
} 




+0

好吧,但他不需要做任何事情,只是返回_email。那么,什么是财产的原因?原因在于未来的使用。 – agnieszka 2009-08-14 12:40:07

2

这...取决于后调用的方法?

我总是用干将&制定者,因为他们创造了这个快捷方式:

公众诠释美孚{获得;组; }

在编译时它被翻译。现在你不可能喜欢它,但它在那里,如果你想要看起来很花哨,你可以稍后再拼出来。

然而,公共,私人,受保护...这都是你想要调整数据的问题。我们大量使用继承,这对我们来说是一种非常普遍的方法,所以只有孩子才能编辑某些属性。

protected _foo; 
public Foo 
{ 
    get { return _foo; } 
} //lack of set intentional. 
-1

我不能相信,11分的答案,没有人对此表示:

并非所有的私有字段应该暴露的公共属性。你当然应该使用属性来表达任何需要非私人性质的东西,但是你应该尽可能地保持私人空间的私密性。

+1

重读这个问题 - 在这种情况下,我需要这些私人字段在课堂外可以访问。当然,你不会公开每个领域或给每个领域的财产! – 2009-08-14 12:47:06

+0

实际上,这个问题并没有说明你需要什么,只是关于你看到的每个私人领域的公共财产。如果你的领域需要公共访问,那么他们不是私人领域,并且不符合你问的问题。请编辑该问题以清楚说明_your_代码的内容,而不是您在“SO,codeproject.com”上看到的示例 – 2009-08-14 13:07:40

4

你必须在下列情况下使用性质:

  1. 当你需要的财产,以某种格式序列化数据。
  2. 当您需要覆盖派生类中的属性时。
  3. 当你用某种逻辑实现get和set方法。例如,当你实现Singleton模式。
  4. 当您从接口派生,其中声明了属性。
  5. 当您遇到与Reflection有关的特定问题时。
+2

您为什么认为字段无法序列化? – 2009-08-14 13:08:20