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

时间:2008-09-21 17:22:23

标签: c# oop properties field

我看到很多C#类的示例代码都是这样做的:

public class Point {
    public int x { get; set; }
    public int y { get; set; }
}

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

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; }
    }
}

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

public class Point {
    public int x;
    public int y;
}

要清楚,当您需要对基础数据进行一些翻译时,我理解getter和setter的价值。但是,如果你只是通过这些价值观,它似乎毫无疑问地冗长。

17 个答案:

答案 0 :(得分:47)

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

几年前,{p> Jeff Atwood处理了这个问题。他回顾性地指出的最重要的一点是,在代码中从字段更改为属性是breaking change;任何消耗它的东西都必须重新编译才能使用新的类接口,所以如果你控制之外的任何东西都在消耗你的类,你可能会遇到问题。

答案 1 :(得分:31)

稍后将其更改为更简单:

public int x { get; private set; }

答案 2 :(得分:9)

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

答案 3 :(得分:8)

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

C#可以不同地处理属性和变量。例如,您can't pass properties as ref or out parameters。因此,如果由于某种原因需要更改数据结构并且您正在使用公共变量并且现在需要使用属性,那么您的接口将不得不更改,现在代码访问属性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.");
}

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

答案 4 :(得分:3)

使用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 ; 
}
}

答案 5 :(得分:3)

由于自动实现的getter对属性和实际的私有存储变量使用相同的名称。你怎么能在将来改变它?我认为要说的是使用auto实现而不是字段,以便将来可以更改它,以防万一你需要为getter和setter添加逻辑。

例如:

public string x { get; set; }

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

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

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

private string _x;

public string x { 
    get {return x}; 
    set {
        if (Datetime.TryParse(value)) {
            _x = value;
        }
    }; 
}

这是灵活的意思吗?

答案 6 :(得分:2)

还需要考虑的是绑定和序列化时公共成员的更改效果。这两者通常都依赖于公共属性来检索和设置值。

答案 7 :(得分:2)

此外,您可以在getter和setter上添加断点,但不能在字段上。

答案 8 :(得分:1)

还值得注意的是,您无法进行自动属性Readonly,也无法内联初始化它们。这些都是我希望在将来的.NET版本中看到的东西,但我相信你在.NET 4.0中都不会这样做。

这些天我唯一使用带有属性的支持字段的时候是我的类实现了INotifyPropertyChanged并且我需要在更改属性时触发OnPropertyChanged事件。

同样在这些情况下,当从构造函数传入值时,我直接设置了支持字段(无需尝试激活OnPropertyChangedEvent(此时无论如何都是NULL),我在其他任何地方使用该属性本身。 / p>

答案 9 :(得分:1)

AFAIK生成的CIL界面不同。如果将公共成员更改为属性,则需要更改其公共接口,并且需要重新构建使用该类的每个文件。如果您只更改getter和setter的实现,则不需要这样做。

答案 10 :(得分:1)

也许只是将字段公开,您可以引导您更多Anemic Domain Model

亲切的问候

答案 11 :(得分:0)

像在Wpf / C#中一样,添加getter和setter使变量成为属性。

如果它只是一个公共成员变量,则由于它不是属性(即使是其公共成员变量),也无法从XAML访问。

如果它具有setter和getter,则可以从XAML访问它,因为现在它是一个属性。

答案 12 :(得分:0)

  

为什么我们不只是使用公共字段而不是使用属性   当我们不需要进行验证时,调用访问器(get,set)吗?

  1. 属性是提供灵活机制以只读或仅写的成员
  2. 可以覆盖属性,但不能覆盖字段。

答案 13 :(得分:0)

如果在这种情况下你必须改变获得x和y的方式,你可以稍后添加属性。这是我发现最令人困惑的事情。如果使用公共成员变量,则可以在以后轻松将其更改为属性,并在需要在内部存储值时使用名为_x和_y的私有变量。

答案 14 :(得分:0)

最大的不同之处在于,如果你改变了内部结构,你仍然可以按原样维护getter和setter,改变它们的内部逻辑而不会伤害你的API用户。

答案 15 :(得分:0)

您永远不知道以后是否需要对数据进行一些翻译。如果你隐藏你的成员,你已经准备好了。由于界面保持不变,因此您的班级用户不会注意到您是否添加了翻译。

答案 16 :(得分:-1)

塞特尔和吸气剂原则上是不好的(它们是一种糟糕的OO气味 - 我不会说它们是反模式的,因为它们有时是必要的)。

不,技术上没有区别,而且当我真的想分享对象的访问权限时,我偶尔会将其公之于众,而不是添加一个getter。

setter和getter的方式是“Sold”,你可能需要知道有人正在获得一个值或者更改一个值 - 这只适用于原语。

此规则不包括DAO,DTO和显示对象等属性包对象,因为这些对象不是“OO设计”中对象的含义。 (你没有想到“传递消息”到DAO,它只是一堆属性/值对)。