C# 图解教程 第5版 —— 第7章 深入理解类

7.1 类成员

表7.1 类成员的类型
image-20231018234549929

7.2 成员修饰符的顺序

​ 类成员声明语句由下列部分组成,方括号表示该成分是可选的。

image-20231018234715835
  • 修饰符

    • 必须放在核心声明之前。
    • 多个修饰符可以任意顺序排列。

    例如,下面两行代码在语义上是等价的:

    public static int MaxVal;
    static public int MaxVal;
    
  • 特性

    • 必须放在核心声明之前。
    • 多个特性可以任意顺序排列。
image-20231018234959137
图7.1 特性、修饰符和核心声明的顺序

7.3 实例类成员(*)

7.4 静态字段(*)

7.5 从类的外部访问静态成员

  1. 使用 类名.静态成员 的方式:
image-20231024230157643
图7.2 方式一访问静态成员
  1. 使用 using 声明:
image-20231024230230688
图7.3 方式二访问静态成员

7.5.1 静态字段示例

7.5.2 静态成员的生存期

​ 即使类没有实例,也存在静态成员。

7.6 静态函数成员

  • 类似静态字段,即使没有类的实例,也可以调用静态方法。
  • 静态函数成员不能访问实例成员,但能访问其他静态成员。

7.7 其他静态类成员类型

表7.2 可以声明为静态的类成员类型
image-20231024230602967

7.8 成员常量

​ 用于初始化成员常量的值在编译时必须是可计算的,通常是一个预定义简单类型。

​ C# 中没有全局常量。

7.9 常量与静态量

​ 常量没有自己的储存位置,而是在编译时被编译器替换,类似于 C/C++ 的 #define。

​ 不能将常量声明为 static。

7.10 属性

  • 属性有如下特征:

    • 是命名的类成员。
    • 具有类型。
    • 可以被赋值和读取。
  • 属性是一个函数成员,具有 set 和 get 访问器。

    • 不一定为数据存储分配内存。
    • 它执行代码。

7.10.1 属性声明和访问器

  • set
    • 具有隐式值参 value,类型与属性相同。
    • 可以对 value 进行赋值。
  • get
    • 所有执行路径必须包含一条 return 语句。
    • 返回类型与属性相同。
image-20231024231401308
图7.4 属性声明的语法和结构

7.10.2 属性示例

​ 属性本身没有任何存储,set 决定如何处理发送进来的数据,get 决定将什么数据发送出去。

image-20231024231509385
图7.5 属性示例

7.10.3 使用属性

​ 不能显示地调用访问器。

7.10.4 属性和关联字段

​ 一种常见的方式是:在类中将字段声明为 private 进行封装,同时声明一个 public 属性来控制从类的外部对该字段的访问。和属性关联的字段被称为 后备字段后备存储

image-20231024231936674 image-20231024231946399
图7.6 属性与字段关联示例

​ 两种命名约定:

  1. 属性使用 Pascal 大小写,字段使用 Camel 大小写。
private int firstField;         // Camel 大小写
public  int FirstField {        // Pascal 大小写
    get { return firstField; }
    set { firstField = value; }
}
  1. 属性使用 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 只读和只写属性

image-20231024232755414
图7.7 属性可以只定义一个访问器

7.10.7 属性与公有字段

​ 按照推荐的编码实践,属性比公有字段更好,理由如下:

  • 属性是函数成员而不是数据成员,允许处理输入和输出。
  • 属性可以只读或只写。
  • 编译后的变量和编译后的属性语义不同。
    • 使用属性,后续可以增添处理逻辑而无需重新编译访问它的程序集;使用公有字段却无法做到。

7.10.8 计算只读属性示例(*)

7.10.9 自动实现属性

  • 不声明后备字段(即分配存储)。
  • 不提供访问器的方法体,使用分号替换之。
image-20231024233332624
图7.8 自动实现属性示例

7.10.10 静态属性(*)

7.11 实例构造函数

7.11.1 带参数的构造函数(*)

7.11.2 默认构造函数

​ 如果你为类声明了任何构造函数,那么编译器不会为该类定义默认构造函数。

7.12 静态构造函数

​ 通常,静态构造函数初始化类的静态字段。

  • 初始化类级别的项。
    • 在引用任何静态成员之前。
    • 在创建类的任何实例之前。
  • 静态构造函数在以下方面与实例构造函数不同:
    • 使用 static 关键字。
    • 只能有一个静态构造函数,且不能带参数。
    • 不能有访问修饰符。
    • 不能使用 this 访问器。
    • 不能显示调用,系统会在以下时机自动调用:
      1. 在类的任何实例被创建之前。
      2. 在类的任何静态成员被引用之前。

7.13 对象初始化语句

image-20231024234017510
图7.9 对象初始化语法
  • 初始化的字段和属性必须是 public。
  • 初始化发生在构造方法执行之后,最终赋值结果以初始化语句为准。

7.14 析构函数(*)

7.15 readonly 修饰符

  1. const 字段只能在字段的声明语句中初始化,readonly 字段可以在下列任意位置中设置初始值:

    • 字段声明语句。
    • 类的构造函数(static 字段只能在静态构造函数中完成)。
  2. const 字段的值必须在编译时决定,readonly 字段的值可以在运行时决定。

  3. const 的行为总是静态的,readonly 字段可以:

    • 是实例字段,也可以是静态字段。
    • 在内存中有存储位置。

7.16 this 关键字

​ this 表示对当前实例的引用,不能在任何静态函数成员中使用。其使用范围为:

  • 实例构造函数。
  • 实例方法。
  • 属性和所引起的实例访问器。

​ 实际上,this 很少在代码中使用。

7.17 索引器

​ 可以认为索引器是为类的多个数据成员提供 get 和 set 访问的属性。

7.17.1 什么是索引器

​ 索引器是一组 get 和 set 访问器,与属性类似。

image-20231025214947600
图7.10 索引器的表现形式

7.17.2 索引器和属性

  • 和属性一样,索引器不分配内存。
  • 和属性一样,索引器可以只有一个访问器,也可以两个都有。
  • 和属性一样,实现 get 和 set 访问器的代码不一定要关联到某个字段或属性。
  • 索引器总是实例成员,不能被声明为 static。
  • 索引器和属性都主要用来访问其他数据成员。
    • 属性通常表示单个数据成员。
    • 索引器通常表示多个数据成员。

7.17.3 声明索引器

  • 索引器没有名称,使用关键字 this。
  • 参数列表在方括号中间。
  • 参数列表至少需要声明一个参数。
image-20231025215117469
图7.11 索引器的声明
image-20231025215153887
图7.12 比较索引器声明和属性声明

7.17.4 索引器的 set 访问器

​ 当索引器被用于赋值时,set 访问器被调用,并接受两项数据:

  1. 隐式参数 value,持有要保存的数据。
  2. 索引参数 parameterList,表示数据应该保存到哪里。
image-20231025215551772
图7.13 set访问器声明的语法和含义

7.17.5 索引器的 get 访问器

​ 当使用索引器获取值时,可以通过索引参数调用 get 访问器,指示获取哪个值。

image-20231025215714363
图7.14 get访问器声明的语法和含义

7.17.6 关于索引器的更多内容

​ 和属性一样,不能显示调用 get 和 set 访问器。

7.17.7 为 Employee 示例声明索引器(*)

7.17.8 另一个索引器示例(*)

7.17.9 索引器重载

​ 只要索引器的参数列表不同,类就可以有多个索引器。

7.18 访问器的访问修饰符

  • 默认情况下,成员访问器的访问级别和自身相同。

  • 可以为两个访问器分配不同的访问级别。

    • 仅当成员具有两个访问器时,访问器才可以有修饰符。

    • 两个访问器中只有一个能有访问修饰符;另一个不能,表示和成员的访问级别相同。

      (因为访问器不能同时比成员自身的访问级别更严格)

    • 访问器的访问修饰符的限制需要比成员自身的访问级别更严格。

image-20231025220237145
图7.15 访问器级别的限制性层次

7.19 分部类和分部类型

​ 类的声明可以分割成几个分部类的声明,每个分部类声明必须被标注为 partial class。

  • 每个分部类的声明都含有一些类成员的声明。
  • 类的分分部类声明可以在不同文件中。
  • partial 不是关键字,因此可以在程序其他地方将其用作标识符。
image-20231025220616243
图7.16 使用分部类型来分割类

​ 除了分部类,还可以创建如下两种分部类型:

  • 分部结构。
  • 分部接口。

7.20 分部方法

  • 定义分部方法。

    • 给出签名和返回类型。
    • 实现部分用分号替换。
  • 实现分部方法。

    • 给出签名和返回类型。
    • 用语句块实现方法。

​ 有关分部方法的说明如下:

  1. 签名和返回类型的特征如下:

    • 返回类型必须是 void。
    • 签名不能包括访问修饰符,即分部方法是隐式私有的。
    • 参数列表不能包含 out 参数。
    • 在定义和实现中都必须包含上下文关键字 partial,且放在 void 之前。
  2. 当不声明为 public 时,可以仅有定义部分。此时编译器将移除所有该方法的内部调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蔗理苦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值