差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
csharp:类:嵌套类 [2025/11/17 09:49] – [一、什么时候应该用嵌套类(C# 示例)] 张叶安csharp:类:嵌套类 [2025/11/27 10:21] (当前版本) – [1. 内部类需要被多处复用] 张叶安
行 1: 行 1:
-一、什么时候应该用嵌套类(C# 示例)+====== C# 嵌套类 (Nested Classes) 使用指南 ======
  
-## 1. 嵌套类是外部类的组成部分   +嵌套类(Nested Class)在另一个类内部声明的类。在 C# 中,嵌套类与外部类的关系主要是**访问控制**的关系,而不是对象实的关系
-如 `Person.Address` 很自然地属于 Person+
  
-```csharp+ 
 +**C# 与 Java 的区别**: 
 +在 C# 中,嵌套类默认**不会**自动持有外部类实例的引用(类似于 Java 的 static inner class)。如果需要访问外部类的非静态成员,必须显式传递外部类的实例。 
 + 
 +===== 一、什么时候应该用嵌套类 (最佳实践) ===== 
 + 
 +嵌套类的核心使用原则是:**高内聚,低耦合**。当一个类仅仅服务于另一个类时,嵌套是最好的选择。 
 + 
 +==== 1. 逻辑上的组成部分 (强组合关系) ==== 
 + 
 +当子对象离开父对象就没有独立存在的意义,或者其定义仅在父对象上下文中有效时。 
 + 
 +<code csharp>
 public class Person public class Person
 { {
行 16: 行 27:
     }     }
  
-    public class Address  // 嵌套类+    // 嵌套类:Address 被视为 Person 的一部分 
 +    public class Address 
     {     {
         public string City { get; }         public string City { get; }
行 28: 行 40:
     }     }
 } }
-```+</code>
  
-使用由   +**核心原**: 
-Address 不会被其他模块独立使用   +  * **封装性**:将 `Address` 定义在 `Person` 内部,表明了它是 `Person` 的附属信息。 
-- 内聚性更强   +  * **命名空间整洁**:避免了全局命名空间中出大量零散的小类(如 `PersonAddress`)。
-- 隐藏实细节+
  
----+==== 2. 辅助器模式 (Builder / Iterator) ====
  
-## 2. 嵌套类作为外部类的辅助器(例如 builder 或 iterator)  +这是嵌套类最经典的使用场景。Builder(构建者)或 Iterator(迭代器)通常需要访问外部类的私有构造函数私有数据。
  
-```csharp+<code csharp>
 public class User public class User
 { {
行 45: 行 56:
     public int Age { get; }     public int Age { get; }
  
 +    // 私有构造函数:强制外部必须通过 Builder 来创建实例
     private User(string name, int age)     private User(string name, int age)
     {     {
行 59: 行 71:
         {         {
             _name = name;             _name = name;
-            return this;+            return this; // 链式调用
         }         }
  
行 70: 行 82:
         public User Build()         public User Build()
         {         {
 +            // 嵌套类可以访问外部类的 private 构造函数
             return new User(_name, _age);             return new User(_name, _age);
         }         }
     }     }
 } }
-```+</code>
  
-使用由   +**核心原**: 
-Builder 的在意义仅服务 User   +  * **访问权限**:嵌套类拥有访问外部类 `private` 成员的特权。 
-- 避免污染全局命名空间+  * **单一职责**:`Builder唯一职责就是构建 `User`,放外部没有意义
  
----+==== 3. 需要访问外部类的私有成员 ====
  
-## 3. 非静态嵌套类需要访问外类成员   +当一个辅助类需要操作主类的内状态字段)但又不想把这些字段公开(public给全世界时。
-C# 的嵌套类默认 *不* 自动持外部类实例需要你传入+
  
-```csharp+<code csharp>
 public class Machine public class Machine
 { {
-    private int _state = 0;+    private int _state = 0; // 私有状态
  
     public class Handler     public class Handler
行 94: 行 106:
         private readonly Machine _machine;         private readonly Machine _machine;
  
 +        // C# 嵌套类不自动持有外部引用,需要手动传入
         public Handler(Machine machine)         public Handler(Machine machine)
         {         {
行 101: 行 114:
         public void Increase()         public void Increase()
         {         {
 +            // 关键点:可以直接访问外部类的 private 字段 _state
             _machine._state++;             _machine._state++;
         }         }
     }     }
 } }
-```+</code>
  
-使用由   +**核心原**: 
-Handler 的功能依赖 Machine 的状态   +  * **白盒操作**:`Handler` 是 `Machine` “自己人”,可以安全地操作内部数据,而无需破坏 `Machine封装性(即不需要把 `_state` 设为 public)。
-- 嵌套使结构更清晰+
  
----+===== 二、什么时候不应该用嵌套类 (反模式) =====
  
-# 二、什么时候不应该用嵌套类(C# 示例)+用嵌套类会导致代码难以阅读、难以测试,甚至引发内存问题。
  
-## 1. 内部类可能被多个外部模块复用   +==== 1. 内部类需要被多复用 ====
-这会导致奇怪的层级结构。+
  
-```csharp+如果一个类不仅被外部类使用,还被其他模块使用,它就不应该被嵌套。 
 + 
 +<code csharp>
 public class Order public class Order
 { {
-    public class MathUtils  // 不应该嵌套+    // 错误示范:MathUtils 是通用工具,不属于 Order 独有 
 +    public class MathUtils  
     {     {
         public static int Add(int a, int b) => a + b;         public static int Add(int a, int b) => a + b;
     }     }
 } }
-```+</code> 
 + 
 + 
 +**后果**:其他类如果要用这个工具,必须写成 `Order.MathUtils.Add(...)`,这不仅啰嗦,而且让人困惑:为什么做加法运算需要依赖 `Order` 类?
  
-错误原因   
-- MathUtils 与 Order 毫无关系   
-- 应该独立成为工具类 
  
----+==== 2. 生命周期管理风险 (内存泄漏) ====
  
-## 2. 嵌套类生命周期外部类不一致   +如果嵌套类的实例生命周期外部类长,且嵌套类持有了外部类的引用,导致外部类无法被垃圾回收(GC)
-例如:后台任务外部类活得更久+
  
-```csharp+<code csharp>
 public class Controller public class Controller
 { {
-    public class BackgroundWorker  // 不应该非静态嵌套类+    // 假设这一个很大的对象,占用大量内存 
 +    private byte[] _largeData = new byte[1024 * 1024];  
 + 
 +    public class BackgroundWorker 
     {     {
-        // 可能会导致持有外部类引用过久(如果你传进来)+        public Controller Parent { get; set; } 
 +         
 +        public void Run() { 
 +            // 模拟长时间运行的任务 
 +            while(true) { /* ... */ } 
 +        }
     }     }
 } }
-``` +</code>
- +
-如果 BackgroundWorker 长期运行,而你在其中引用了 Controller,就会阻止 Controller 被回收。 +
- +
-解决方式   +
-- 不把长期对象设计为嵌套类   +
-- 或使用静态/独立类 + 弱引用+
  
----+**核心原理**: 
 +  * 如果 `BackgroundWorker` 被单独传递给一个线程池运行,而它又引用了 `Controller`,那么只要任务没结束,巨大的 `Controller` 对象就永远无法释放。 
 +  * **建议**:对于长期运行的后台任务,尽量使用独立的类,或者确保不持有外部类的强引用(使用 `WeakReference`)。
  
-## 3. 嵌套层级影响可读性  +==== 3. 嵌套层级深 ====
  
-```csharp+<code csharp>
 public class A public class A
 { {
行 164: 行 182:
         public class C         public class C
         {         {
-            public class D { }+            public class D { } // A.B.C.D
         }         }
     }     }
 } }
-```+</code>
  
-没有明确业务意义时应避免这种构。+**核心原理**: 
 +  * **可读性灾难**:这种代码被称为“俄罗斯套娃”代码,极难阅读和维护。 
 +  * **重困难**:如果将来要把 `D` 移出来,所有引用它的代码都需要修改
  
----+==== 4. 逻辑关系松散 ====
  
-## 4. 内部类与外部类逻辑强   +仅仅为了“整理代码”而把不相的类塞进去是对的。
-例如:+
  
-```csharp+<code csharp>
 public class Company public class Company
 { {
-    public class Logger  // 不应该嵌套+    // 错误示范:Logger 是通用的基础设施,不是 Company 的业务组成 
 +    public class Logger  
     {     {
         public void Log(string message) => Console.WriteLine(message);         public void Log(string message) => Console.WriteLine(message);
     }     }
 } }
-``` +</code>
- +
-Logger 并不是 Company 的组成部分,应该是独立工具类。 +
- +
---- +
- +
-# 总结(C# 场景) +
- +
-应该用嵌套类当:   +
-- 逻辑上只属于外部类   +
-- 属于外部类的组成部分   +
-- 辅助外部类工作   +
-- 更强的封装性和结构清晰度   +
- +
-不应该用嵌套类当:   +
-- 类具有可复用性   +
-- 生命周期与外部类不一致   +
-- 业务上没有强逻辑归属   +
-- 过深层级影响可读性  +
  
----+**核心原理**: 
 +  * **单一职责原则 (SRP)**:`Company` 应该只负责公司的业务逻辑,不应该负责定义日志工具。`Logger` 应该是一个独立的类或接口。
  
 +===== 总结 =====
  
 +^ 维度 ^ 建议嵌套 ^ 建议独立 ^
 +| **复用性** | 仅被外部类使用 | 被多个模块使用 |
 +| **访问权限** | 需要访问外部类 private 成员 | 仅访问 public 成员 |
 +| **生命周期** | 与外部类共存亡 | 独立于外部类存在 (如后台任务) |
 +| **逻辑关系** | 是外部类的一部分 (Is-Part-Of) | 与外部类无关 (工具类/通用服务) |

该主题尚不存在

您访问的页面并不存在。如果允许,您可以使用创建该页面按钮来创建它。

  • csharp/类/嵌套类.1763344167.txt.gz
  • 最后更改: 2025/11/17 09:49
  • 张叶安