在 C# 编程世界中,类(Class) 是最基础且最强大的引用类型。它不仅是数据的容器,更是逻辑的封装体。
本文将基于 C# 的最新特性,深度提炼类中的关键技术点,帮助开发者构建更健壮的对象模型。
1. 字段与常量的"静与动"
类的数据成员主要由字段和常量构成。
- 只读字段 (readonly) :这是确保不可变性的利器。
readonly字段只能在声明时或构造函数中赋值。它与const的不同之处在于:const是编译时静态赋值,而readonly是运行时赋值,具有更高的灵活性。 - 常量 (const):常量隐式为静态的。编译器在编译时会直接将常量值嵌入到调用处(类似宏替换),因此它仅支持内置的基本类型。
2. 方法的高级形态
方法是类行为的体现。除了基础的实例方法,C# 还提供了多种灵活的形态:
- 表达式体方法 :当逻辑只有一行时,使用
=>(胖箭头)替代花括号,代码更简洁。 - 局部方法 :在方法内部定义另一个方法,这能有效地将辅助逻辑隐藏在特定范围内。从 C# 8 开始,支持静态局部方法,防止意外访问外部变量,降低耦合。
- 方法签名:请记住,方法的唯一性由其名称和参数类型顺序决定(不含参数名和返回值类型)。
3. 构造与解构的艺术
- 隐式与显式构造:如果你未定义任何构造器,编译器会生成一个无参公有构造器;一旦你定义了任何构造器,该隐式构造器便消失。
- 解构器 (Deconstructor) :这是构造器的"镜像操作"。通过定义
Deconstruct方法并使用out参数,你可以轻松将对象拆解为多个变量。
4. 属性(Property)的进化
属性是 C# 的语法精华,它表面像字段,实则封装了 get/set 逻辑。
- Init-only setter (C# 9) :使用
init替代set。这允许对象在初始化器中赋值,但一旦初始化完成,该属性即变为只读。这完美解决了"创建后不可变"但"创建时需灵活赋值"的需求。 - 自动属性与初始化器:大大减少了样板代码,并支持直接给属性赋默认值。
5. 索引器(Indexer)
索引器让你的类像数组或字典一样被访问。通过定义 this[int index],你可以为集合类型的类提供直观的访问接口。现代 C# 还支持在索引器中使用 Index 或 Range 类型(如 myObj[1..3])。
6. 静态构造器与静态类
- 静态构造器:每个类型只会执行一次。它在类被实例化或静态成员被访问时触发。它是初始化复杂静态数据的理想场所。
- 静态类 :标记为
static的类不能被实例化或继承,且只能包含静态成员(如Math类)。
7. 进阶:分部类型与分部方法
partial 关键字允许将一个类的定义分散在多个文件中。
- 应用场景:这在自动代码生成(如 WinForms 窗体设计器或 Roslyn 源代码生成器)中至关重要。
- 扩展分部方法 (C# 9):允许程序员定义钩子,而由代码生成器负责实现,反向增强了生成代码的灵活性。
核心技术对比表
| 特性 | 关键字 | 生命周期/作用域 | 关键说明 |
|---|---|---|---|
| 只读字段 | readonly |
运行时确定 | 构造完成后不可变 |
| 常量 | const |
编译时确定 | 值直接嵌入调用处 |
| 只写初始化 | init |
初始化阶段 | C# 9 新特性,初始化后只读 |
| 名称获取 | nameof |
编译时 | 返回符号的字符串名,方便重构 |
技术思考 :
在设计类时,优先考虑不可变性 (使用 readonly 和 init)和封装性 (使用属性而非公有字段)。合理利用 partial 和 local methods 可以让大型项目的代码维护变得更加优雅。