自动实施的获取者和设置者与公共领域

我看到很多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; } } } 

我的问题是为什么。 上述做法和使这些成员公开领域之间有什么function差异,如下所示?

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

要清楚的是,当我需要对底层数据进行一些翻译时,我明白getter和setter的价值。 但是,如果你只是通过价值观,似乎不必要的冗长。

我倾向于同意(似乎是不必要的冗长),尽pipe这是一个问题,我们的团队还没有解决,所以我们的编码标准仍然坚持所有类别的详细属性。

杰夫·阿特伍德几年前就处理过这个问题。 他回顾性地提到的最重要的一点是,从一个领域到一个属性的变化是你的代码的一个突破性的变化 。 任何消耗它的东西都必须重新编译,以便与新的类接口一起工作,所以如果你的控制之外有什么东西在消耗你的类,那么你可能会遇到问题。

稍后将其更改为更简单:

 public int x { get; private set; } 

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

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

C#可以有时对待属性和variables。 例如,您不能将属性作为ref或outparameter passing 。 所以,如果你由于某种原因需要改变数据结构,并且你正在使用公共variables,现在你需要使用属性,你的接口将不得不改变,现在访问属性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."); } 

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

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

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

 class SomeControl { private string _SomeProperty ; public string SomeProperty { if ( _SomeProperty == null ) return (string)Session [ "SomeProperty" ] ; else return _SomeProperty ; } } 

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

例如:

 public string x { get; set; } 

例如你已经使用了很多次,你不想破坏你的代码。

你如何改变自动获取设置…例如对于设置你只允许设置一个有效的电话号码格式…你如何改变代码,只有class级将被改变?

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

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

这是什么意思,使其灵活?

当涉及到绑定和序列化时,还需要考虑到公共成员变更的影响。 这两者往往依靠公共属性来检索和设置值。

AFAIK生成的CIL接口是不同的。 如果您将公共成员更改为属性,则您正在更改其公共接口,并且需要重build每个使用该类的文件。 如果只更改getter和setter的实现,则这不是必需的。

也许只是把领域公开,你可能会导致你更多的贫血域模型 。

亲切的问候

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

同样值得注意的是,您不能将自动属性设为只读,并且不能将它们初始化为内联。 这两个都是我希望在将来的.NET版本中看到的东西,但是我相信在.NET 4.0中你都不能这样做。

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

同样在这种情况下,当从构造函数传入值时,我直接设置了后台字段(无需尝试和触发OnPropertyChangedEvent(在这个时候这将是NULL),在我使用属性本身的任何地方。

你永远不知道你以后可能不需要翻译数据。 如果你隐藏了你的成员,你已经准备好了。 如果您添加翻译,您的类的用户不会注意到,因为界面保持不变。

最大的区别是,如果你改变了你的内部结构,你仍然可以维护getter和setter,改变它们的内部逻辑而不会伤害你的API的用户。

如果在这种情况下你必须改变你如何得到x和y,你可以稍后添加属性。 这是我觉得最困惑的。 如果您使用公共成员variables,则可以稍后轻松将其更改为属性,如果需要在内部存储该值,则可以使用名为_x和_y的私有variables。

安装人员和吸气人员原则上是不好的(他们是一个糟糕的OO气味 – 我不会说他们是反模式,因为他们有时真的是必要的)。

不,技术上没有什么区别,当我真的想分享访问对象的时候,我偶尔会公开决定而不是添加一个getter。

制定者和获得者的方式是“销售”,就是你可能需要知道某个人正在获得价值或改变一个价值 – 这只对原始人有意义。

像DAO,DTO和显示对象这样的属性包对象被排除在这个规则之外,因为这些对象并不是真正的“OOdevise”意义上的对象。 (你不会想到将消息传递给DAO,它只是一堆属性/值对)。