# 内部类 概念: 也叫==嵌套类== 就是把一个类写在另一个类的内部 本质上它还是类,所以仍然是[[值类型和引用类型|引用类型]] 通常用法: 1. 给外部类当“小零件”用,不想单独暴露出去 2. 把关系很紧密的类型写在一起,减少命名污染 3. 配合[[成员变量和访问修饰符|访问修饰符]]控制谁能访问 语法: ```Csharp class Outer { public class Inner { } } ``` 案例: ```Csharp class Person { private string name = "小明"; public class Pet { public void LookOwner(Person p) { cw(p.name); } } } Person p = new Person(); Person.Pet pet = new Person.Pet(); pet.LookOwner(p); //输出 小明 ``` ↑ `Pet` 是 `Person` 的内部类,所以外部使用时一般写成 `Person.Pet` 注意: 1. 更规范的说法一般是==嵌套类(nested class)== 2. ==类中的内部类如果不写访问修饰符,默认是private== 3. 外部访问时通常写 `外部类名.内部类名` 4. ==C# 的内部类不会自动绑定外部类对象==,想访问外部对象的数据,一般要把外部类对象传进去 5. 内部类主要是为了==封装和组织代码==,不是继承 ---- # 分部类 概念: 在C#里更常见的叫法是==分部类== 用 `partial` 关键字把==同一个类拆到多个文件或多个位置== 编译时会把这些内容==合并成同一个类== 通常用法: 1. 一个类太长了,拆开写更清楚 2. 自动生成代码和手写逻辑分开 3. 多人协作时减少都挤在一个文件里的冲突 语法: ```Csharp public partial class Player { } ``` 在另一个文件里也可以继续写: ```Csharp public partial class Player { } ``` 案例: ```Csharp //Player_Base.cs public partial class Player { public string name; public void Move() { cw("移动"); } } //Player_Fight.cs public partial class Player { public int atk; public void Attack() { cw("攻击"); } } Player p = new Player(); p.Move(); p.Attack(); cw(p.atk); ``` ↑虽然写在两个文件里,但编译后它们还是==同一个 `Player` 类== 注意: 1. ==每一部分都要写 `partial`==,少一处都不行 2. 一般要保证它们是==同名、同命名空间==的一组类型 3. 分部类是==编译时合并==,不是继承,也不是复制出多个类 4. 很适合配合工具自动生成代码,比如“工具生成一部分,自己手写一部分” 5. `partial` 不只类能用,结构体和接口也能用,但这节先记类 6. 不要为了拆而拆,拆太碎反而更难找代码 ---- # 分部方法 概念: 分部方法就是写在==分部类==中的特殊方法 也是用 `partial` 关键字声明 一般是一边先声明“这里留个钩子”,另一边再决定要不要实现 通常用法: 1. 给自动生成代码留扩展点 2. 把“框架流程”和“自定义逻辑”拆开 3. 某些逻辑可选,有需要时再补实现 语法: 先声明: ```Csharp partial void OnCreated(); ``` 再在同一个分部类型的另一部分里实现: ```Csharp partial void OnCreated() { cw("创建完成"); } ``` 案例: ```Csharp //Player_Base.cs public partial class Player { public Player() { OnCreated(); } partial void OnCreated(); } //Player_Extend.cs public partial class Player { partial void OnCreated() { cw("玩家初始化完成"); } } ``` ↑ 这种写法很适合“主逻辑在自动生成文件里,扩展逻辑在自己文件里” 注意: 1. ==分部方法只能写在分部类型里==,普通类里不能单独这么用 2. 它本质上是“声明部分”和“实现部分”配对 3. 如果只是最经典那种可选分部方法,一般写法是==没有访问修饰符、返回 `void`、不能有 `out` 参数== 4. 这种“可选分部方法”如果没写实现,==编译器会把声明和调用一起移除== 5. ==如果你给它加了访问修饰符,或者返回值不是 `void`,通常就不能再省略实现== 6. 所以记忆上可以理解成:简单钩子可以不实现,复杂正式方法通常必须实现 ---- 引用: 1. Microsoft Learn: [Nested types (C# Programming Guide)](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/nested-types) 2. Microsoft Learn: [Partial Classes and Members (C# Programming Guide)](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods) 3. Microsoft Learn: [partial type (C# Reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/partial-type) 4. Microsoft Learn: [Partial member (C# Reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/partial-member) #封装 #核心