这本书讲解 C# 语言十分详细,我将其中的重要内容整理成条款,以备忘。
1. 类成员声明的顺序: [ 特性 ] [ 修饰符 ] 核心声明。特性和修饰符在各自范围内都可以以任意顺序放置。
2. 类的静态字段 被类的所有实例 共享 ,所有实例 都访问同一内存位置 。
3. 实例成员在实例被创建时开始存在,当实例被销毁时停止存在。如果静态字段有初始化语句,那么该字段在类的任何静态成员被使用之前 初始化。
4. 静态函数成员不能 访问实例成员 ,但可以访问其他静态成员 。
5. 用于初始化成员常量的值在编译期必须是可计算的 ,通常是预定义类型或由它们组成的表达式,如: enum 、 string 、 int 、 float ,而 struct 、 class 等不行 ,声明的同时必须初始化 ,其后不能对其再赋值。
6. 成员常量隐式为静态的 ,所以不能显示声明为 static ,它们对类的每个实例都是“可见的”,在类外部需使用类名去访问,但成员常量没有自己的存储位置 ,它们在编译时被编译器替换,被硬编码到程序集中 ( 类似于 C/C++ 的 #define ) 。
7. 属性 get 访问器必须包含一条 return 语句,返回一个属性类型的值。 set 和 get 的顺序可任意。属性与和它相关联的字段有几种命名约定,如:字段使用 Camel 大小写 ( 首字母小写 ) 或下划线 + camel ,属性使用 Pascal 大小写。
8. 属性的两个访问器必须至少定义一个,否则会产生编译错误。属性并非必须和字段关联,也可以类似方法做一些其他操作,如:
Class MyClass
{
private int a=3, int b=4;
public int Op // 只读属性
{
get {return Math.Sqrt((a * a) + (b * b));}
}
}
9. 和属性关联的字段叫做后备字段,编译器不会为属性分配内存,而是将数据保存到后备字段,对后备字段进行读写。
10. C# 3.0 增加了自动实现的属性:允许只声明属性而不声明后备字段 ,编译器会根据属性的类型分配存储空间;编译器将创建一个私有的匿名后备字段,该字段只能通过属性的 get 和 set 访问器进行访问。访问器的方法体只能声明为分号,必须同时声明 get 和 set 访问器。若要创建 readonly 的自动实现属性,需要将它的 set 访问器设为 private 。这样,当属性中不需要其他逻辑时,自动实现的属性可以使属性声明变得更加简洁。
11. 属性也可以声明为 static ,但只能访问 static 字段 。
12. 实例构造函数在类的每个新实例创建的时候执行,如果希望能从类的外部 创建类的实例,需要声明为 public , new 运算符使用类的构造函数之一去创建类的实例。
13. 如果程序员定义了一个或多个 构造函数,则编译器将不会为该类定义默认构造函数。
14. 静态构造函数初始化类层次的项目,这发生在任何静态 成员被引用之前 ,任何类的实例 成员被创建之前 ,如类的静态字段。如果类中包含 Main 方法 ,则该类的静态构造函数将在调用 Main 方法之前 执行 。一个类中只能有一个 静态构造函数,而且不能带参数 ,也不能有访问修饰符,因为它是私有 的 。
15. 静态构造函数不能访问 所在类的实例 成员,也不能使用 this 访问器。系统会自动调用静态构造函数,所以不能显示调用 ,静态构造函数不可被继承 。
16. 如果类中含有带初始化式的静态字段,则在执行该类的静态构造函数时,会首先按照文本顺序执行那些初始化式。如果没有编写静态构造函数,而类中包含带有初始化式的静态字段,那么编译器会自动生成默认的静态构造函数。
17. C# 3.0 增加了对象初始化列表 ( 对象初始化器 ) ,允许在创建新的对象实例时设置字段和属性的值,有 2 种形式:一种包括构造函数的参数列表,另一种不包括。被初始化的成员在创建对象的代码 ( 大多是在类的外部 ) 中必须是可访问的 ( 如 public) ,成员初始化在构造函数完成之后发生。
18. 析构函数在类的实例被销毁之前 清理或释放非 托管资源。析构函数只对类的实例起作用 ,没有静态析构函数,不能显示地调用析构函数,析构函数会带来性能上的损耗,而且只应该释放对象自己的外部非托管资源,不应该访问其他对象 ,因为无法确定这些对象是否已被收集。只有实例才有析构函数。
19. CLR 的垃圾收集器会在对象从托管堆中被移走之前的某点 调用析构函数,但不能确定具体时间,如果代码包含需要及时清理的非托管资源 ,应采用标准模式,在类中实现 IDisposable 接口,接口中清理资源的代码封装在一个 Dispose 方法中, Dispose 方法需要程序员手动去调用,系统不会自动去调用它。
20. 在实现 Dispose 方法的类中要声明一个布尔型字段以弄清清理是否已经发生,在 Dispose 方法中应当调用 GC.SuppressFinalize() 方法,该方法告诉 CLR 不要调用该类的析构函数。具体示例参看 6.12节的代码。
21. readonly 字段可以在声明时设置它的值,如同 const( 而 const 只能在字段的声明中进行初始化 ) ,另外还可以在类的任何构造函数 中 ,如果是 static 字段,初始化不许在 static 构造函数中完成 。
22. const 字段的值必须在编译期决定,而 readonly 字段的值可以在运行期决定,因此可以在不同 的构造函数中设置不同 的值 。 readonly 字段既可以是实例字段,也可以是静态字段,它在内存中有存储位置。
23. this 关键字在类中使用,是对当前实例的引用,只能用在实例 构造函数、实例 方法、属性和索引的实例访问器。 this 通常用来区分类的成员和本地变量或参数以及作为调用方法的实参。在方法内使用 this 引用字段,以区分相同名字的参数。
24. 属性允许使用索引访问类实例的字段,好像该实例是字段的数组一样。和属性一样,索引不用分配内存来存储,数据保存在相关联的实例的字段。
25. 索引可以想象成是提供获取和设置类的多个数据成员的属性,索引本身可以是任何类型的,但应至少有一个访问器,而且不能声明为 static 。索引实现 get 和 set 的代码并非一定要关联到一个类的某个字段或属性,可以做任何事情或什么也不做,只要 get 返回某个指定类型的值即可。
26. 索引没有名称,在名称的位置是关键字 this ,参数列表在方括号中间,且必须至少声明一个 参数。在 get 和 set 中的代码必须检查索引参数,它们所使用的参数列表和索引声明中的相同。类中重载 的索引必须有不同的参数列表 。
27. 属性和索引 ( 都是函数成员 ) 在默认情况下,成员的两个访问器有和成员自身相同的访问级别。如果一个成员的两个访问器都存在时,其中的一个 访问器可以设置访问修饰符,但要注意:访问器的修饰符必须比成员的访问修饰符级别更高 。
28. 类型修饰符 partial 不是关键字,在其他上下文中,可以在程序中把它用作标识符,但直接用在关键字 class 、 struct 或 interface 之前时,它表示分部类型。类似的上下文关键字可参见 P12 表 2-4 。
29. 分部方法是在分部类中声明在两个部分中的方法,分部方法有两个部分:定义部分,实现部分。定义部分给出签名和返回类型加一个分号,实现部分同正常的方法定义一样。
30. 分部方法的返回类型必须为 void ,它的两个部分必须都包括 partial ,直接放在 void 之前,分部方法是隐式私有 的,不能有包括访问修饰符 ,不能包含 out 参数 。可以有定义部分而没有实现部分,但如果有分部方法的实现,则必须有定义部分。可参见 P106 的代码 Add 方法。