人们经常被告知,我们应该通过为类字段创建getter和setter方法(C#中的属性)来保护封装,而不是将字段暴露给外界。
但是在很多情况下,只有一个字段可以保存值,并且不需要任何计算即可获取或设置。 对于这些,我们都将使用以下数字:
public class Book
{
private string _title;
public string Title
{
get{ return _title; }
set{ _title = value; }
}
}
好吧,我有一个坦白的话,我忍不住写所有的东西(真的,不必写它,而不必去看它),所以我流氓并使用了公共领域。
然后是C#3.0,我看到它们添加了自动属性:
public class Book
{
public string Title {get; set;}
}
哪个比较整洁,我对此很感激,但实际上,与仅公开场地有何不同?
public class Book
{
public string Title;
}
#1楼
从字段更改为属性会破坏合同(例如,要求重新编译所有引用代码)。 因此,当您与其他班级(任何公共(且受一般保护)的成员)建立交流点时,您需要计划未来的发展。 通过始终使用属性来执行此操作。
如今,让它成为自动属性并没有什么,下线三个月后,您就知道要使其延迟加载,并在getter中放入一个空检查。 如果您使用过字段,那么这最好是重新编译的更改,而在最坏的情况下则是不可能的,这取决于谁以及您的程序集还依赖什么。
#2楼
在我前段时间遇到的一个相关问题中 ,有一个指向Jeff博客上的帖子的链接,解释了一些区别。
反射在变量和属性上的工作方式不同,因此,如果您依赖反射,则使用所有属性会更容易。
您无法与变量进行数据绑定。
将变量更改为属性是一项重大更改。 例如:TryGetTitle(out book.Title); // requires a variable
#3楼
这全部与版本控制和API稳定性有关。 在版本1中没有什么区别-但是稍后,如果您决定需要在版本2中将此属性设为带有某种类型的错误检查的属性,则无需更改API-除了在任何地方,都无需更改代码属性的定义。
#4楼
忽略API问题,我发现使用属性最有价值的就是调试。
CLR调试器不支持数据断点(大多数本机调试器都支持)。 因此,不可能在读取或写入类的特定字段时设置断点。 在某些调试方案中,这是非常有限的。
由于属性是作为非常薄的方法实现的,因此可以在读取和写入其值时设置断点。 这使他们在田野上有很大的优势。
#5楼
如果您稍后决定通过与集合或数据库进行比较来检查标题是否唯一,则可以在属性中执行此操作,而无需更改依赖该标题的任何代码。
如果仅使用公共属性,则灵活性会降低。
在不违反合同的情况下,额外的灵活性对我而言是使用属性最重要的事情,在我真正需要灵活性之前,自动生成才最有意义。