自动实现的getter和setter与公共领域

时间:2020-03-06 14:30:38  来源:igfitidea点击:

我看到很多Cclasses的示例代码可以做到这一点:

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,在不损害API用户的情况下更改其内部逻辑。

稍后将其更改为以下内容也更加简单:

public int x { get; private set; }

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

几年前,杰夫·阿特伍德(Jeff Atwood)处理了这个问题。他回顾性指出的最重要的一点是,从字段更改为属性是代码中的重大更改。任何消耗它的东西都必须重新编译才能使用新的类接口,因此,如果控件之外的任何东西正在消耗类,则可能会遇到问题。

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

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

Ccan有时会不同地对待属性和变量。例如,我们不能将属性作为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.");
}

从一开始就使用属性可以避免这种情况,并且我们可以随意调整基础实现,而无需破坏客户端代码。

AFAIK生成的CIL接口是不同的。如果将公共成员更改为属性,则要更改它的公共接口,并且需要重建使用该类的每个文件。如果仅更改getter和setter的实现,则没有必要。

在绑定和序列化方面,更改对公共成员的影响也要考虑。这两种方法通常都依赖于公共属性来检索和设置值。

也许只是将字段公开,我们可能会导致我们进入一个更贫血的领域模型。

亲切的问候

setter和getter原则上是不好的(它们是一种很差的OO气味-我会说它们是反模式,这是因为有时确实是必要的)。

不,从技术上讲没有什么区别,并且当我最近真的想共享对某个对象的访问权限时,我有时会使其成为final最终对象,而不是添加getter。

设置者和获取者被"出售"的方式是,我们可能需要知道某人正在获得价值或者改变价值-这仅对基元有意义。

此规则中不包括诸如DAO,DTO和显示对象之类的属性包对象,因为它们不是"对象"一词真正的" OO设计"含义中的对象。 (我们不会想到将消息传递给DAO,它只是一堆属性/值对)。

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

由于自动实现的getter在属性和实际的私有存储变量中使用相同的名称。将来如何更改?我认为要说的是使用自动实现而不是字段,以便将来在需要向getter和setter添加逻辑的情况下可以对其进行更改。

例如:

public string x { get; set; }

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

如何更改自动吸气剂设置程序...例如,对于setter,我们仅允许设置有效的电话号码格式...如何更改代码,以便仅更改类?

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

private string _x;

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

这就是我们要使其具有灵活性吗?

另外,可以在getter和setter上设置断点,但不能在字段上设置断点。

还值得注意的是,我们不能将"自动属性"设置为"只读",也不能内联初始化它们。这些都是我希望在将来的.NET版本中看到的,但是我相信我们不能在.NET 4.0中实现。

这些天,我唯一一次使用带有属性的后备字段是当我的类实现INotifyPropertyChanged时,并且当属性更改时,我需要触发OnPropertyChanged事件。

同样在这些情况下,当从构造函数传递值时,我直接设置了后备字段(无需尝试触发OnPropertyChangedEvent(无论如何此时都将为NULL),在其他任何地方,我都使用属性本身。