1 一个具体例子
首先我们定义一个Person的类,其中包含一个按照传统方式定义的属性Age,一个自动属性Name,代码如下:
public class Person { //性别 private bool sender; public bool Sender { get { return sender; } set { sender = value; } } private int age; //字段 public int Age //属性 { get { return age; } set { if (value < 0 || value > 100) { throw new ArgumentOutOfRangeException("年龄不合法"); } else { age = value; } } } public string Name//自动属性 { get; set; } }
从中我们可以看出:
传统属性:定义比较繁琐、臃肿。比如性别,需要定义一个私有的字段 然后定义属性来封装该字段
自动属性 :只需要定义 ,不需要实现的属性语法,不需要定义字段
2.自动属性的本质
使用发编译工具Reflector 查看其编译后的IL代码,截图如下:
从IL中我们可以看出编译器自动为属性Name生成一个私有的字段<Name>k__BackingField 和两个方法:Get_Name和Set_Name方法,这个两个方法用来封该私有字段
自动属性的本质:一个私有字段 一个Get方法和一个Set方法
3 总结
自动属性主要用在对字段的读写权限的封装,帮助减少程序员代码,让代码更好看;但实质上在编译时,还是会自动生成一个对应的字段,这样从IL代码中,可知自动属性就和传统的属性没有区别了,因此可以说这些都是编译器的功劳。
4 思考
1. 什么时候我们使用自动属性呢?
如何属性只是简简单单对字段进行封装,没有对字段附加逻辑,就是用自动属性;反之,我们就是用传统属性的定义方式来实现,比如字段age,我们需要判断年龄是否合法,此时就不能使用自动属性。
2. 抽象属性
public abstract class User { //自动属性 public string Name { get; set; } //定义抽象属性 public abstract int Age { get; set; } }
反编译如下
从反编译的IL代码看出,抽象属性并没有自动生成一个默认的字段,因为抽象属性就是为了子类重写的,因此这里没有提供其具体实现