自动实现的getter和setter与公共字段

tcl*_*lem 71 c# oop field properties

我看到很多C#类的示例代码执行此操作:

public class Point {
    public int x { get; set; }
    public int y { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

或者,在旧代码中,具有显式私有支持值并且没有新的自动实现属性:

public class Point {
    private int _x;
    private int _y;

    public int x {
        get { return _x; }
        set { _x = value; }
    }

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

我的问题是为什么.在执行上述操作与仅将这些成员设为公共字段之间是否有任何功能差异,如下所示?

public class Point {
    public int x;
    public int y;
}
Run Code Online (Sandbox Code Playgroud)

为了清楚起见,当您需要对基础数据进行一些翻译时,我理解了getter和setter的价值.但是,如果你只是传递价值观,那似乎是不必要的冗长.

Dex*_*ter 48

我倾向于同意(它似乎不必要地冗长),虽然这已成为我们团队尚未解决的问题,因此我们的编码标准仍然坚持所有类的详细属性.

杰夫阿特伍德几年前处理过这个问题.他回顾性地指出的最重要的一点是,从一个领域转变为一个属性是你的代码中的一个重大变化 ; 任何消耗它的东西都必须重新编译才能使用新的类接口,所以如果你控制之外的任何东西都在消耗你的类,你可能会遇到问题.

  • 在C#中,具有get和set的属性编译为一对方法,如get_PropertyName()和set_PropertyName(type value).C#中的属性语法只是语法糖.属性可以执行代码,因此将它们编译为与字段相同的代码是没有意义的. (9认同)
  • JIT编译器确实优化了一个属性,没有代码等同于一个字段,因此没有理由不使用C#3.0+中的简写语法来使用属性 (9认同)

Bra*_*son 31

稍后将其更改为更简单:

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

  • 我...甚至不知道你能做到这一点. (11认同)
  • @Merus仅在C#3.0中 (2认同)

Jos*_*gle 9

它封装了这些成员的设置和访问.如果从现在起一段时间,代码的开发人员需要在访问或设置成员时更改逻辑,则可以在不更改类的合同的情况下完成.

  • @ Ajedi32从技术上来说他们不是*同一份合同.如果将其从字段更改为属性(或将属性更改为字段),则必须重新编译访问该成员的任何内容.因为在访问属性与字段时编译的IL不同. (2认同)

Rob*_*ton 8

我们的想法是,即使底层数据结构需要更改,也不必更改类的公共接口.

C#可以不同地处理属性和变量.例如,您不能将属性作为ref或out参数传递.因此,如果由于某种原因需要更改数据结构并且您正在使用公共变量并且现在需要使用属性,那么您的接口将不得不更改,现在代码访问属性x可能不再像它变量那样编译X:

Point pt = new Point();
if(Int32.TryParse(userInput, out pt.x))
{
     Console.WriteLine("x = {0}", pt.x);
     Console.WriteLine("x must be a public variable! Otherwise, this won't compile.");
}
Run Code Online (Sandbox Code Playgroud)

从一开始就使用属性可以避免这种情况,您可以随意调整底层实现,而不必破坏客户端代码.


Yor*_*iev 5

Setter 和 Getter 使您能够添加额外的抽象层,在纯 OOP 中,您应该始终通过对象提供给外部世界的接口访问对象......

考虑一下这段代码,它将把你保存在 asp.net 中,如果没有 setter 和 getter 提供的抽象级别,这是不可能的:

class SomeControl
{

private string _SomeProperty  ;
public string SomeProperty 
{
  if ( _SomeProperty == null ) 
   return (string)Session [ "SomeProperty" ] ;
 else 
   return _SomeProperty ; 
}
}
Run Code Online (Sandbox Code Playgroud)


Nap*_*Nap 5

由于自动实现的 getters 对属性和实际的私有存储变量采用相同的名称。未来如何改变?我认为所说的要点是使用自动实现而不是字段,以便将来如果您需要向 getter 和 setter 添加逻辑,您可以更改它。

例如:

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

例如,您已经多次使用 x 并且您不想破坏您的代码。

如何更改自动获取器设置器...例如,对于设置器,您只允许设置有效的电话号码格式...如何更改代码以便仅更改类?

我的想法是添加一个新的私有变量并添加相同的 x getter 和 setter。

private string _x;

public string x { 
    get {return _x}; 
    set {
        if (Datetime.TryParse(value)) {
            _x = value;
        }
    }; 
}
Run Code Online (Sandbox Code Playgroud)

这就是你说的让它变得灵活的意思吗?