CLR via C# 属性 无参属性 自动实现的属性
如果只是为了封装一个支持字段而创建属性,C#还提供了一种更简洁的语法,称为自动实现的属性(Automatically Implemented Property,AIP)。
像上面的Name属性。
声明属性而不提供get/set方法的实现,C#会自动为你声明一个私有字段。字段的类型是string,也就是属性的类型。另外,编译器会自动实现get_Name和set_Name方法,分别返回和设置字段中的值。
//--
和直接声明名为Name的public string字段相比,AIP的优势在哪里?
事实上,两者存在一处重要的区别。使用AIP,意味着你已经创建了一个属性。访问该属性的任何代码实际都会调用get和set方法。如果以后决定自己实现get和/或set方法,而不是接受编译器的默认实现,访问属性的任何代码都不必重新编译。然而,如果将Name声明为字段,以后又想把它更改为属性,那么访问字段的所有代码都必须重新编译才能访问属性方法。
//--
1.作者建议避免使用AIP,理由是:字段声明语法可能包含初始化部分,所以要在一行代码中声明并初始化字段。但没有简单地语法初始化AIP。所以,必须在每个构造器方法中显式初始化每个AIP。
2.运行时序列化引擎将字段名持久存储到序列化的流中。AIP的支持字段名称有编译器决定,每次重写编译代码都可能更改这个名称。因此,任何类型只要含有一个AIP,就没办法对该类型的实例进行反序列化。在任何想要序列化或反序列化的类型中,都不要使用AIP功能。
3.调试时不能在AIP的get或set方法上添加断点,所以不好检测应用程序在什么时候获取或设置这个属性。相反,手动实现的属性可设置断点,查错更方便。
//--
还要注意,如果使用AIP,属性必然是可读和可写的。换言之,编译器肯定同时生成get和set方法。这个设计的道理在于,只写字段不能读取值有什么用?类似的只读字段肯定是有默认值的。另外,由于不知道编译器生成的支持字段到底是什么名字,所以代码只能用属性名访问属性。另外,任何访问器方法(get或set)要显式实现,两个访问器方法都必须显式实现,就不能使用AIP了。换言之,AIP是作用于整个属性的;要么都用,要么都不用。不能显式实现一个访问器方法,而让另一个自动实现。