C# 类与结构的区别详解

71

在 C# 中,类(Class)和结构(Struct)是两种不同的数据类型,尽管它们都能封装数据和行为,但在设计目的和底层机制上有显著区别。

1. 类型分类

类是引用类型(Reference Type):

  • 变量存储的是对象的引用(内存地址),多个变量可以指向同一个对象。

结构是值类型(Value Type):

  • 变量直接存储数据的副本,赋值时会发生值的复制。

// 类(引用类型)
MyClass obj1 = new MyClass();
MyClass obj2 = obj1; // obj2 和 obj1 指向同一对象

// 结构(值类型)
MyStruct s1 = new MyStruct();
MyStruct s2 = s1;    // s2 是 s1 的独立副本

2. 内存分配

类实例分配在堆(Heap)上,由垃圾回收器(GC)管理。

结构实例通常分配在栈(Stack)上(除非被装箱或作为类的成员),生命周期由作用域决定,效率更高。

3. 继承与多态

类支持继承和多态,可以继承自另一个类,并实现多个接口。

结构不能继承其他结构或类,只能实现接口(隐式继承 System.ValueType)。

class Animal { }          // 类可以继承
class Dog : Animal { }    // 合法

struct Point { }          // 结构不能继承
// struct Point3D : Point { } // 非法!

4. 默认构造函数

类可以有显式无参构造函数,如果没有定义,编译器会生成一个默认构造函数。

结构不能定义无参构造函数,编译器自动生成一个默认构造函数,将所有字段初始化为默认值(如数值为0)

struct MyStruct
{
    public int X;
    // public MyStruct() { } // 非法!结构不能自定义无参构造函数
}

5. 初始化与 new

类必须通过 new 实例化(否则为 null)。

结构可以不使用 new,直接声明变量(但需显式初始化所有字段)。

MyClass obj; // 未初始化,默认 null
// obj.Method(); // 运行时错误(NullReferenceException)

MyStruct s;    // 已分配内存,但字段未初始化
// s.X = 10;    // 必须先初始化字段才能使用

6. 性能考量

结构适合轻量级对象(如坐标 Point、颜色 Color),避免堆分配和 GC 开销。

类适合需要复杂逻辑、生命周期较长或较大的对象。

7. 适用场景

使用类:

  • 需要继承或多态。

  • 需要引用语义(共享数据)。

  • 对象较大或频繁修改(避免值复制开销)。

使用结构:

  • 小规模、不可变(Immutable)的数据(如 DateTime)。

  • 需要值语义(独立副本)。

  • 避免堆分配(高频创建的场景)

8. 总结表格

类型

引用类型

值类型

内存分配位置

栈(通常)

继承

支持

不支持

默认构造函数

可自定义无参构造函数

不能自定义无参构造函数

初始化

必须用 new

可直接声明(需初始化字段)

适用场景

复杂对象、共享数据

轻量级数据、频繁复制