文章目录
- 7.1 类成员
- 7.2 成员修饰符的顺序
- 7.3 实例类成员(*)
- 7.4 静态字段(*)
- 7.5 从类的外部访问静态成员
- 7.5.1 静态字段示例
- 7.5.2 静态成员的生存期
- 7.6 静态函数成员
- 7.7 其他静态类成员类型
- 7.8 成员常量
- 7.9 常量与静态量
- 7.10 属性
- 7.10.1 属性声明和访问器
- 7.10.2 属性示例
- 7.10.3 使用属性
- 7.10.4 属性和关联字段
- 7.10.5 执行其他计算
- 7.10.6 只读和只写属性
- 7.10.7 属性与公有字段
- 7.10.8 计算只读属性示例(*)
- 7.10.9 自动实现属性
- 7.10.10 静态属性(*)
- 7.11 实例构造函数
- 7.11.1 带参数的构造函数(*)
- 7.11.2 默认构造函数
- 7.12 静态构造函数
- 7.13 对象初始化语句
- 7.14 析构函数(*)
- 7.15 readonly 修饰符
- 7.16 this 关键字
- 7.17 索引器
- 7.17.1 什么是索引器
- 7.17.2 索引器和属性
- 7.17.3 声明索引器
- 7.17.4 索引器的 set 访问器
- 7.17.5 索引器的 get 访问器
- 7.17.6 关于索引器的更多内容
- 7.17.7 为 Employee 示例声明索引器(*)
- 7.17.8 另一个索引器示例(*)
- 7.17.9 索引器重载
- 7.18 访问器的访问修饰符
- 7.19 分部类和分部类型
- 7.20 分部方法
7.1 类成员
7.2 成员修饰符的顺序
类成员声明语句由下列部分组成,方括号表示该成分是可选的。
-
修饰符
- 必须放在核心声明之前。
- 多个修饰符可以任意顺序排列。
例如,下面两行代码在语义上是等价的:
public static int MaxVal; static public int MaxVal;
-
特性
- 必须放在核心声明之前。
- 多个特性可以任意顺序排列。
7.3 实例类成员(*)
7.4 静态字段(*)
7.5 从类的外部访问静态成员
- 使用
类名.静态成员
的方式:
- 使用
using
声明:
7.5.1 静态字段示例
7.5.2 静态成员的生存期
即使类没有实例,也存在静态成员。
7.6 静态函数成员
- 类似静态字段,即使没有类的实例,也可以调用静态方法。
- 静态函数成员不能访问实例成员,但能访问其他静态成员。
7.7 其他静态类成员类型
7.8 成员常量
用于初始化成员常量的值在编译时必须是可计算的,通常是一个预定义简单类型。
C# 中没有全局常量。
7.9 常量与静态量
常量没有自己的储存位置,而是在编译时被编译器替换,类似于 C/C++ 的 #define。
不能将常量声明为 static。
7.10 属性
-
属性有如下特征:
- 是命名的类成员。
- 具有类型。
- 可以被赋值和读取。
-
属性是一个函数成员,具有 set 和 get 访问器。
- 不一定为数据存储分配内存。
- 它执行代码。
7.10.1 属性声明和访问器
- set
- 具有隐式值参 value,类型与属性相同。
- 可以对 value 进行赋值。
- get
- 所有执行路径必须包含一条 return 语句。
- 返回类型与属性相同。
7.10.2 属性示例
属性本身没有任何存储,set 决定如何处理发送进来的数据,get 决定将什么数据发送出去。
7.10.3 使用属性
不能显示地调用访问器。
7.10.4 属性和关联字段
一种常见的方式是:在类中将字段声明为 private 进行封装,同时声明一个 public 属性来控制从类的外部对该字段的访问。和属性关联的字段被称为 后备字段 或 后备存储。
两种命名约定:
- 属性使用 Pascal 大小写,字段使用 Camel 大小写。
private int firstField; // Camel 大小写
public int FirstField { // Pascal 大小写
get { return firstField; }
set { firstField = value; }
}
- 属性使用 Pascal 大小写,字段使用 Camel 大小写 + 下划线。
private int _secondField; // Camel 大小写 + 下划线
public int SecondField { // Pascal 大小写
get { return _secondField; }
set { _secondField = value; }
}
7.10.5 执行其他计算
C# 7.0 引入了 lambda 表达式语法,在函数体只有一个表达式时可以使用:
int theRealValue = 10;
int MyValue {
set => theRealValue = value > 100 ? 100 : value;
get => theRealValue;
}
7.10.6 只读和只写属性
7.10.7 属性与公有字段
按照推荐的编码实践,属性比公有字段更好,理由如下:
- 属性是函数成员而不是数据成员,允许处理输入和输出。
- 属性可以只读或只写。
- 编译后的变量和编译后的属性语义不同。
- 使用属性,后续可以增添处理逻辑而无需重新编译访问它的程序集;使用公有字段却无法做到。
7.10.8 计算只读属性示例(*)
7.10.9 自动实现属性
- 不声明后备字段(即分配存储)。
- 不提供访问器的方法体,使用分号替换之。
7.10.10 静态属性(*)
7.11 实例构造函数
7.11.1 带参数的构造函数(*)
7.11.2 默认构造函数
如果你为类声明了任何构造函数,那么编译器不会为该类定义默认构造函数。
7.12 静态构造函数
通常,静态构造函数初始化类的静态字段。
- 初始化类级别的项。
- 在引用任何静态成员之前。
- 在创建类的任何实例之前。
- 静态构造函数在以下方面与实例构造函数不同:
- 使用 static 关键字。
- 只能有一个静态构造函数,且不能带参数。
- 不能有访问修饰符。
- 不能使用 this 访问器。
- 不能显示调用,系统会在以下时机自动调用:
- 在类的任何实例被创建之前。
- 在类的任何静态成员被引用之前。
7.13 对象初始化语句
- 初始化的字段和属性必须是 public。
- 初始化发生在构造方法执行之后,最终赋值结果以初始化语句为准。
7.14 析构函数(*)
7.15 readonly 修饰符
-
const 字段只能在字段的声明语句中初始化,readonly 字段可以在下列任意位置中设置初始值:
- 字段声明语句。
- 类的构造函数(static 字段只能在静态构造函数中完成)。
-
const 字段的值必须在编译时决定,readonly 字段的值可以在运行时决定。
-
const 的行为总是静态的,readonly 字段可以:
- 是实例字段,也可以是静态字段。
- 在内存中有存储位置。
7.16 this 关键字
this 表示对当前实例的引用,不能在任何静态函数成员中使用。其使用范围为:
- 实例构造函数。
- 实例方法。
- 属性和所引起的实例访问器。
实际上,this 很少在代码中使用。
7.17 索引器
可以认为索引器是为类的多个数据成员提供 get 和 set 访问的属性。
7.17.1 什么是索引器
索引器是一组 get 和 set 访问器,与属性类似。
7.17.2 索引器和属性
- 和属性一样,索引器不分配内存。
- 和属性一样,索引器可以只有一个访问器,也可以两个都有。
- 和属性一样,实现 get 和 set 访问器的代码不一定要关联到某个字段或属性。
- 索引器总是实例成员,不能被声明为 static。
- 索引器和属性都主要用来访问其他数据成员。
- 属性通常表示单个数据成员。
- 索引器通常表示多个数据成员。
7.17.3 声明索引器
- 索引器没有名称,使用关键字 this。
- 参数列表在方括号中间。
- 参数列表至少需要声明一个参数。
7.17.4 索引器的 set 访问器
当索引器被用于赋值时,set 访问器被调用,并接受两项数据:
- 隐式参数 value,持有要保存的数据。
- 索引参数 parameterList,表示数据应该保存到哪里。
7.17.5 索引器的 get 访问器
当使用索引器获取值时,可以通过索引参数调用 get 访问器,指示获取哪个值。
7.17.6 关于索引器的更多内容
和属性一样,不能显示调用 get 和 set 访问器。
7.17.7 为 Employee 示例声明索引器(*)
7.17.8 另一个索引器示例(*)
7.17.9 索引器重载
只要索引器的参数列表不同,类就可以有多个索引器。
7.18 访问器的访问修饰符
-
默认情况下,成员访问器的访问级别和自身相同。
-
可以为两个访问器分配不同的访问级别。
-
仅当成员具有两个访问器时,访问器才可以有修饰符。
-
两个访问器中只有一个能有访问修饰符;另一个不能,表示和成员的访问级别相同。
(因为访问器不能同时比成员自身的访问级别更严格)
-
访问器的访问修饰符的限制需要比成员自身的访问级别更严格。
-
7.19 分部类和分部类型
类的声明可以分割成几个分部类的声明,每个分部类声明必须被标注为 partial class。
- 每个分部类的声明都含有一些类成员的声明。
- 类的分分部类声明可以在不同文件中。
- partial 不是关键字,因此可以在程序其他地方将其用作标识符。
除了分部类,还可以创建如下两种分部类型:
- 分部结构。
- 分部接口。
7.20 分部方法
-
定义分部方法。
- 给出签名和返回类型。
- 实现部分用分号替换。
-
实现分部方法。
- 给出签名和返回类型。
- 用语句块实现方法。
有关分部方法的说明如下:
-
签名和返回类型的特征如下:
- 返回类型必须是 void。
- 签名不能包括访问修饰符,即分部方法是隐式私有的。
- 参数列表不能包含 out 参数。
- 在定义和实现中都必须包含上下文关键字 partial,且放在 void 之前。
-
当不声明为 public 时,可以仅有定义部分。此时编译器将移除所有该方法的内部调用。