我应该使用公共属性和私有字段或公共字段来获取数据吗?

Cal*_*ers 55 .net c# coding-style properties

在我看过的大部分代码中(在SO上,我都会在我自己的代码中使用codeproject.com),我已经看到为一个类包含的每个私有字段创建公共属性,即使它们是最多的基本类型get; set;:

private int myInt;
public int MyInt 
{
     get { return myInt; }
     set { myInt = value }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:这与以下方面有何不同:

public int MyInt;
Run Code Online (Sandbox Code Playgroud)

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

Joh*_*lan 33

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

特别

  • 反射在变量与属性上的工作方式不同,因此如果依赖于反射,则更容易使用所有属性.
  • 您无法对变量进行数据绑定.
  • 将变量更改为属性是一个重大变化.

  • 使用属性比使用字段更可取,因为您可以更改get和set块中的语句,而无需更改依赖于该属性的类. (2认同)

Max*_*ing 22

三个原因:

  1. 您不能像子属一样覆盖子类中的字段.
  2. 您最终可能需要更复杂的getter或setter,但如果它是一个字段,更改它会破坏API.
  3. 惯例.这就是它的完成方式.

我确信有更多的理由我只是没想到.

在.Net 3.x中,您可以使用如下自动属性:

public int Age { get; set; }
Run Code Online (Sandbox Code Playgroud)

而不是旧的学校方式自己像这样声明你的私人领域:

private int age;

public int Age
{
    get { return age; }
    set { age = value; }
}
Run Code Online (Sandbox Code Playgroud)

这使得它像创建一个字段一样简单,但没有突破性的变化问题(除此之外).

  • @Russell Steen - 当然这是一个突破性的变化.仅仅因为它在C#中看起来*相同并不意味着**是相同的.您正在将字段访问更改为方法调用,这完全不同,并且需要重新编译任何调用代码. (6认同)
  • "你最终可能需要一个更复杂的getter或setter,但如果它是一个字段,改变它会破坏API." 并不是的.你可以放心地来自:public int Joe; 私有的int _joe; public int Joe {get {// do something} set {// do something}}您可能需要更改许多内部引用,但这不会破坏您的API. (2认同)

agn*_*zka 8

当您创建私有字段名称和实际获取并设置名称字段值的简单公共属性名称时

public string Name
{
   get { return name; }
}
Run Code Online (Sandbox Code Playgroud)

并且你在你的课外的任何地方使用这个属性,有一天你决定这个类的Name属性实际上会引用lastName字段(或者你想要返回一个字符串"我的名字:"+名称),你只需更改属性内的代码:

public string Name
{
   get { return lastName; //return "My name: "+name; }
}
Run Code Online (Sandbox Code Playgroud)

如果您在外部代码中的任何位置使用公共字段名称,则必须在使用它的任何位置将名称更改为lastName.


Pat*_*and 5

那确实有所作为.可以在对象实例不知道的情况下更改公共数据.使用getter和setter,对象始终知道已经进行了更改.

请记住,封装数据只是迈向更好的结构化设计的第一步,它本身并不是最终目标.