显示页面讨论反向链接回到顶部 本页面只读。您可以查看源文件,但不能更改它。如果您觉得这是系统错误,请联系管理员。 ====== C# 结构体 (Struct) 详解 ====== 在 C# 中,**结构体 (Struct)** 是一种轻量级的数据类型。与类(Class)不同,结构体是**值类型 (Value Type)**,这使得它在特定的性能敏感场景下具有极大的优势。 ===== 1. 什么是结构体? ===== 结构体使用 ``struct`` 关键字定义。它通常用于封装包含少量相关变量的数据组,例如坐标点、颜色值或复数。 <code csharp> public struct Point { public int X { get; } public int Y { get; } public Point(int x, int y) { X = x; Y = y; } public override string ToString() => $"({X}, {Y})"; } </code> ===== 2. 结构体 vs 类 (Struct vs Class) ===== 这是 C# 面试和架构设计中最常见的问题。核心区别在于**内存分配**和**赋值行为**。 ^ 特性 ^ 结构体 (Struct) ^ 类 (Class) ^ | **类型种类** | **值类型** (Value Type) | **引用类型** (Reference Type) | | **存储位置** | 通常在**栈 (Stack)** 上(或内联在其他对象中) | 总是分配在**托管堆 (Heap)** 上 | | **赋值行为** | **复制值**。赋值给新变量时,会拷贝整个数据副本。 | **复制引用**。赋值给新变量时,两个变量指向同一个对象。 | | **垃圾回收 (GC)** | **不涉及 GC**(随作用域自动释放),对 GC 压力极小。 | **需要 GC** 回收,频繁创建销毁会造成 GC 压力。 | | **继承** | **不支持继承**(不能继承其他类或结构体),但可以实现**接口 (Interface)**。 | 支持完整的继承体系 (Inheritance)。 | | **默认值** | 不能为 null(除非使用 Nullable<T>,即 `int?`),默认值为所有字段归零。 | 默认为 null。 | | **析构函数** | 不支持析构函数 (Finalizer)。 | 支持析构函数。 | ===== 3. 结构体 vs 枚举 (Struct vs Enum) ===== 虽然它们都是值类型,但用途完全不同。 ^ 特性 ^ 结构体 (Struct) ^ 枚举 (Enum) ^ | **本质** | 复合数据结构。可以包含字段、属性、方法、构造函数等。 | 命名常量的集合。底层通常只是一个整数 (int, byte 等)。 | | **数据承载** | 用于存储**多个**相关联的数据(如 X 和 Y 坐标)。 | 用于表示**单一**的状态、选项或模式(如 Color.Red, Week.Monday)。 | | **逻辑** | 可以包含业务逻辑(方法)。 | 不能包含方法(虽然可以使用扩展方法模拟)。 | | **用途** | 描述一个“对象”或“实体”的轻量级表现。 | 描述一组有限的“选项”或“类别”。 | **示例对比:** * **Enum:** `GameState { Playing, Paused, GameOver }` (只表示状态) * **Struct:** `PlayerState { int Health; Vector3 Position; }` (包含具体数据) ===== 4. 什么时候应该使用结构体? ===== 微软官方建议,只有当类型满足以下**所有**条件时,才考虑使用结构体: - **逻辑上表示单一值**:类似于基本类型(int, double),如坐标点、复数。 - **实例体积很小**:通常建议实例大小小于 **16 字节**。如果大于这个大小,复制值的开销可能会超过引用传递的开销。 - **不可变 (Immutable)**:结构体创建后,其字段值最好不要改变。 - **不需要频繁装箱 (Boxing)**:如果需要频繁将该类型转换为 `object` 或接口,装箱操作会抵消结构体的性能优势。 ===== 5. 最佳实践:不可变性 (Immutability) ===== 在使用结构体时,强烈建议将其设计为**不可变**的。因为结构体是值拷贝,修改副本不会影响原始变量,这在可变结构体中极易导致难以排查的 Bug。 **错误示范 (可变结构体):** <code csharp> struct MutablePoint { public int X; public int Y; } // ... MutablePoint p1 = new MutablePoint { X = 10 }; MutablePoint p2 = p1; // p2 是 p1 的副本 p2.X = 20; // 此时 p1.X 仍然是 10,这往往不符合直觉 </code> **正确示范 (不可变结构体):** <code csharp> readonly struct ImmutablePoint { public int X { get; } public int Y { get; } public ImmutablePoint(int x, int y) { X = x; Y = y; } } // 使用 readonly 关键字可以强制编译器检查不可变性 </code> ===== 6. 总结 ===== * **Struct**: 为了性能(高频计算、海量小对象、减少 GC)。 * **Class**: 为了面向对象特性(继承、多态、大型业务对象)。 * **Enum**: 为了代码可读性和状态管理。 登录 Detach Close 该主题尚不存在 您访问的页面并不存在。如果允许,您可以使用创建该页面按钮来创建它。 csharp/变量/结构体.txt 最后更改: 2025/12/22 11:22由 张叶安 登录