关于C#:属性(无额外处理)与公共字段

Property(with no extra processing) vs public field

本问题已经有最佳答案,请猛点这里访问。

每当对属性的可信性有疑问时,我看到大多数讨论都围绕函数/方法与属性展开。但是,我也想知道使用与相关私有字段和公共字段直接相关联的属性的令人信服的原因,在没有其他处理的最常见的get/set行为中,我的意思是这样的

1
public string CustomerName;

VS

1
2
3
4
5
6
private string customerName;
public string CustomerName
{
get{return customerName;}
set(string value){this.customerName=value;}
}


如果您以后需要添加其他行为,您可以获得源代码/二进制兼容性,您可以添加断点,而且它在哲学上更干净(关注行为,而不是存储机制)。

注意,在C 3中,您不需要整个后一个块:

1
public string CustomerName { get; set; }

有关更多信息,请参阅我关于"为什么属性重要"的文章。


  • 可以重写或至少在派生类中创建"new"属性

  • 在这一点上,人们期望属性被暴露,字段被隐藏。如果有人要对你的班级进行反思(它在温莎城堡、NHibernate等工具中越来越普遍),这是一个有差异的世界,他们很可能不会去检查暴露的领域。


  • 我注意到一个有用的财产使用。如果要将对象集合绑定到DataGrid、DataGridView或其他可绑定控件,则唯一可识别的可计算名称是属性而不是公共字段。


    这主要是Java中的一个bug。在许多其他语言(python、delphi、groovy)中,编译器将为您生成getter和setter,除非您提供代码。

    这意味着您可以在groovy中使用"public"字段,编译器将自动生成并调用setter/setter。如果你需要在一个字段改变时做额外的魔法,你可以引入一个专门的设置器,一切都会工作。

    这就是现实与设计冲突的地方之一。Java设计者不希望编译器做任何你看不到的事情。很多年前似乎是个好主意,结果不太好。


    您还可以使用属性提供一些基本验证。例如,要防止将属性设置为无效状态,如高度的负值:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    private int height;
    public int Height
    {
      get{ return height; }
      set
      {
         if (value > 0)
         {
             height = value;
         }
      }
    }


    即使没有任何额外的处理,仍然有一些好处1。良好的编码实践。一般来说,最好不要将字段直接暴露在外部类中,而是只允许它们通过这个额外的抽象层进行访问。即使没有额外的处理,保持一致仍然很好,因为您可能在代码中的其他地方需要它。2。稍后,当有多个其他项目依赖于您的时,您可能需要将字段更改为属性。这将需要重新编译所有内容。三。可以将事件与它们一起使用,例如将处理程序绑定到PropertyChanging或PropertyChanged事件。对于字段,这是不可能的。