Public Fields versus Automatic Properties
我们经常被告知,我们应该通过为类字段生成getter和setter方法(C中的属性)来保护封装,而不是将字段暴露给外部世界。
但有很多时候,一个字段只是在那里保存一个值,不需要任何计算来获取或设置。对于这些,我们都会做这个数字:
1 2 3 4 5 6 7 8 9 10 | public class Book { private string _title; public string Title { get{ return _title; } set{ _title = value; } } } |
嗯,我有一个忏悔,我不能忍受写所有这些(真的,它不必写,它必须看),所以我去了流氓和使用公共领域。
接下来是C 3.0,我看到它们添加了自动属性:
1 2 3 4 | public class Book { public string Title {get; set;} } |
哪一个更整洁,我很感激,但是,真的,有什么不同于仅仅建立一个公共领域?
1 2 3 4 | public class Book { public string Title; } |
在我之前的一个相关问题中,有一个链接指向杰夫博客上的一篇文章,解释了一些不同之处。
属性与公共变量
- 反射在变量和属性上的工作方式不同,所以如果您依赖于反射,则更容易使用所有属性。
- 不能对变量进行数据绑定。
将变量更改为属性是一种破坏性的更改。例如:
1TryGetTitle(out book.Title); // requires a variable
忽略API问题,我发现使用属性最有价值的是调试。
clr调试器不支持数据断点(大多数本机调试器都支持)。因此,不可能在类的特定字段的读或写上设置断点。在某些调试场景中,这是非常有限的。
因为属性是作为非常瘦的方法实现的,所以可以在其值的读写上设置断点。这使他们在田野上有了一条腿。
从字段更改为属性会破坏合同(例如,需要重新编译所有引用代码)。因此,当您与其他类(任何公共(和一般受保护的)成员)有一个交互点时,您需要为将来的增长做计划。始终使用属性来执行此操作。
今天让它成为一个汽车属性是没有意义的,3个月后你会意识到你想让它懒惰地加载,并在getter中设置一个空检查。如果您使用了字段,则这最多是一个重新编译更改,最坏是不可能的更改,这取决于谁和其他什么依赖于您的程序集。
只是因为没人提到:您不能在接口上定义字段。因此,如果必须实现一个定义属性的特定接口,自动属性有时是一个非常好的特性。
一个巨大的差异,往往被忽视,并没有提到任何其他的答案:压倒性。可以声明虚拟属性并重写它们,但不能对公共成员字段执行相同的操作。
与公共字段相比,自动实现的属性的另一个优点是,您可以将set访问器设置为私有或受保护的,从而为定义了它的对象类提供比公共字段更好的控制。
制作字段
这都是关于版本控制和API稳定性的。在版本1中没有区别,但在以后的版本中,如果您决定需要将此属性设置为具有某种类型的错误签入版本2,则不必更改API-除了属性的定义之外,任何地方都不更改代码。
我发现一件非常有用的事情,以及所有的代码和测试原因是,如果它是一个属性与一个字段,那么Visual Studio IDE将向您显示一个属性而不是字段的引用。
如果稍后决定检查标题是否唯一,通过与集合或数据库进行比较,可以在属性中执行此操作,而不更改依赖于该标题的任何代码。
如果只使用一个公共属性,那么您的灵活性就会降低。
在不破坏契约的情况下,额外的灵活性对于我使用属性是最重要的,而且,在我真正需要灵活性之前,自动生成是最有意义的。