pic*_*ypg 24

它封装领域产生的编译器,并提供你的,classstruct开发人员无需通过简单修改破坏你的API在内部以后更新它的能力get/ set你关心的部分.

比如,突然之间永远不想回归null?您只需将空值更改为get即可get { return storedName ?? ""; }.当然,这意味着你突然需要手动控制变量,但这是一个支付灵活性的小代价.


第一个用途是字段声明的示例.第二个用途是自动实现的属性的示例.

提供直接访问字段通常是不好的做法.然而,.NET团队注意到很多getter/setter基本就是这样.例如,请考虑以下事项:

// C#
public string Name
{
    get { return name; }
    set { name = value; }
}

// Without properties (or a Java implementation)
public void setName(String name)
{
    this.name = name;
}

public String getName()
{
    return name;
}
Run Code Online (Sandbox Code Playgroud)

无论哪种方式,真正暴露一个领域真是太多了.但是,通常情况下,作为开发人员,您需要返回并更改内部处理字段的方式,但如果您可以侥幸逃脱,则不希望破坏甚至影响其他代码.

这就是为什么使用直接访问字段是不好的.如果您提供对字段的直接访问,但需要更改使用该字段的内容,则使用该字段的所有代码也必须更改.如果使用属性(甚至方法),则可以更改内部代码,并且可能不会影响外部代码.

请考虑以下示例:

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

之后您决定需要在setter周围引发更改和更改事件.如果你暴露了一个字段,那么是时候进行重大的重写了.如果您使用了属性(或方法),那么您可以在那里添加逻辑.您突然失去了自动实现属性的好处,但您获得了在不破坏现有代码的情况下重构类的能力.

private string name;
public event NameChangingEventHandler NameChanging;
public event NameChangedEventHandler NameChanged;

public string Name
{
    get { return name; }
    set
    {
        OnNameChanging(/*...*/);
        name = value;
        OnNameChanged(/*...*/);
    }
}

protected virtual void OnNameChanging(/*...*/) { }
protected virtual void OnNameChanged(/*...*/) { }
Run Code Online (Sandbox Code Playgroud)

所有这些都维护着您的公共API,并且不需要该类用户(代码的其余部分或使用您的API的外部开发人员)的工作.突破性变化并不总是可以避免,但避免直接访问字段是尝试确保不会发生变化的一个很好的步骤.自动实现的属性是一种快速,简便的方法.

(不相关:键入此功能时断电,我很高兴我的浏览器保存了大部分内容!)

  • @SLC:其他代码会注意到差异.在引擎盖下,`string name;`声明对象中存储指向字符串的指针的位置.`string name {get; set;}`声明一组过程,可用于向对象询问字符串,或告诉对象存储它(存储该字符串的位置由编译器自动生成).因为它们是如此不同,所以使用它们的实际指令是不同的 - 所以如果你从一个改为另一个,那么除非你重新编译,否则其他代码将会中断. (4认同)
  • 这种方式是有道理的,但如果你有`字符串名称;`以后你决定'裤子,我想限制集; 为了不为空',你可以把它改成字符串名{get; 肯定会设置{..}}?其他代码将执行myObject.name并且不会注意到差异...... (2认同)