C#中类,抽象类,构造函数,结构体,接口,重载和重写
1. 类(Class)
- 本质:引用类型,分配在托管堆上。
- 特点:支持继承(单继承)、支持多态、可以有字段/属性/方法/构造函数。
- 场景:描述业务实体(如
User、Order),包含复杂状态和行为。
2. 结构体(Struct)
- 本质:值类型,通常分配在栈上(或作为类成员时在堆上)。
- 特点:隐式密封(不能继承其他类,但可以实现接口);轻量级;适合存储小型、不可变的数据。
- 注意:在 C# 10 之前,结构体不能定义显式的无参构造函数;C# 10 之后允许,但必须显式初始化所有字段。
3. 静态类(Static Class)
- 本质:密封的抽象类(无法被实例化或继承)。
- 特点:只能包含静态成员(方法、属性、字段);全局唯一。
- 场景:工具类/帮助类(如
Math、FileHelper)。
4. 抽象类(Abstract Class)
- 本质:部分实现的基类,无法被实例化。
- 特点:可以包含状态(字段)、具体方法(有实现)和抽象方法(无实现,强制子类重写)。
- 场景:提供公共基础设施(如
Animal作为基类,提供Name属性,定义抽象方法MakeSound)。
5. 接口(Interface)
- 本质:行为契约,仅定义成员签名(C# 8 之后允许默认实现,但核心理念仍是契约)。
- 特点:不包含实例字段;支持多重实现(一个类可实现多个接口)。
- 场景:解耦、依赖注入、定义通用能力(如
IDisposable、IEnumerable)。
6. 构造函数(Constructor)
- 实例构造函数:初始化对象的实例字段,配合
new调用。 - 静态构造函数:初始化静态成员,在类型第一次被引用前自动调用,且只执行一次(线程安全)。
- 私有构造函数:防止外部实例化(常用于单例模式或工具类)。
7. 重载(Overload)—— 编译时多态
- 定义:同一个类中,方法名相同,但参数列表(类型、数量、顺序)不同。
- 特征:与返回类型无关,与访问修饰符无关。
public void Log(string msg) { } public void Log(string msg, int code) { } // 重载8. 重写(Override)—— 运行时多态
- 定义:子类重新实现父类标记为
virtual或abstract的方法。 - 特征:必须使用
override关键字;不能重写sealed或static方法。 - 对比隐藏(
new):override会替换基类逻辑(多态生效),new仅隐藏基类成员(多态失效)
9.Sealed 方法(密封方法)
- 必须配对使用:
sealed必须和override一起出现(即public sealed override void Method())。 - 不能单独使用:你不能在普通方法(非重写方法)上直接写
sealed,否则编译器报错。 - 不能修饰静态方法:静态方法属于类型本身,不存在重写一说。
高频对比
| 对比维度 | 抽象类 vs 接口 | |
|---|---|---|
| 状态存储 | 抽象类可以有实例字段(状态) | 接口不能有实例字段(C# 8 前) |
| 实现代码 | 可提供部分或全部实现 | 传统仅签名(C# 8 后可有默认实现) |
| 继承/实现 | 单继承 | 多重实现 |
| 构造函数 | 可以有 | 不能有 |
| 适用场景 | “是什么”(is-a)关系,如 狗是动物 | “能做什么”(can-do)关系,如 狗能跑 |
| 对比维度 | 类 vs 结构体 | |
|---|---|---|
| 类型 | 引用类型(堆) | 值类型(栈) |
| 继承 | 支持单继承 | 不支持(隐式密封),但可实现接口 |
| 性能 | 赋值传递引用(开销较小) | 赋值传递副本(拷贝开销随字段增多) |
| 可变性 | 通常可变 | 推荐设计为不可变(readonly struct) |
| 对比维度 | 重载(Overload) vs 重写(Override) | |
|---|---|---|
| 绑定时机 | 编译时绑定 | 运行时绑定 |
| 作用范围 | 同一类或继承链中,横向扩展 | 继承链中,纵向替换 |
| 关键字 | 无特殊关键字 | 基类用virtual,派生类用override |
| 签名要求 | 必须不同(参数不同) | 必须相同(完全相同的方法签名) |