struct赋值时发生深拷贝,状态完全隔离;含引用类型成员时仅复制地址,共享底层数据;不可继承、无自定义无参构造函数,传参默认按值传递。

结构体不是“轻量版类”,它是值类型,语义和行为都和类根本不同。选错类型会在赋值、传参、内存占用甚至逻辑正确性上埋坑。
struct 赋值时发生的是深拷贝,不是引用共享
这是最常被误用的点:把 struct 当成小号 class 用,结果发现修改副本不影响原变量,或者反过来——以为改了副本就该影响原值,结果没生效。
- 赋值、传参、返回值时,
struct自动复制全部字段(包括嵌套的值类型),整个数据被搬走一份 -
class只复制引用地址,多个变量指向同一块堆内存 - 如果
struct里包含引用类型字段(比如string或List),那该字段本身还是引用——拷贝后两个struct指向同一个List,这时候改列表内容会互相影响
示例:
struct Point { public int X, Y; }
var p1 = new Point { X = 10 };
var p2 = p1;
p2.X = 20;
Console.WriteLine(p1.X); // 输出 10 —— 不是 20
struct 不能自定义无参构造函数(C# 10 之前)
你写 public struct S { public S() { } } 会直接编译失败。编译器强制你初始化所有字段,且不允许覆盖默认构造行为。
- 默认构造函数由编译器隐式提供,它把所有字段设为默认值(
int→ 0,bool→false,引用类型 →null) - 你可以定义带参构造函数,但必须显式给每个字段赋值,否则报错:
Field 'S.X' must be fully assigned before control is returned to the caller - C# 10+ 允许在声明时初始化字段(如
public int X = 5;),但无参构造函数仍不可显式定义
错误写法:
public struct BadStruct
{
public int X;
public BadStruct() { } // ❌ 编译错误
struct 作为方法参数传递时默认按值传递
不像 class 那样天然适合“传引用修改”,struct 进入方法就是一份新拷贝,方法内改它不影响调用方原始变量。
- 想让方法修改原
struct,必须加ref或in(只读)修饰符 - 不加修饰符时,即使方法内部对字段赋值,调用方看到的仍是旧值
- 大
struct(比如超过 16 字节)频繁按值传参会带来明显性能开销,这时要考虑是否真该用struct
对比:
void ModifyClass(Class c) { c.Value = 999; } // ✅ 影响原对象
void ModifyStruct(Struct s) { s.Value = 999; } // ❌ 不影响原变量
void ModifyStructRef(ref Struct s) { s.Value = 999; } // ✅ 加 ref 才行
struct 不能继承,也不能被继承
哪怕只写一行 struct Derived : BaseStruct,编译器立刻报错:Type 'Derived' cannot derive from sealed type 'BaseStruct'。
-
struct隐式继承自System.ValueType,而后者是sealed的 - 它可以实现接口(
IEquatable、IComparable等常见接口都鼓励为struct实现),但无法参与继承链 - 如果你需要多态或基类共用逻辑,别硬套
struct,老实用class
容易忽略的一点:泛型约束 where T : struct 要求传入类型必须是值类型,但这个约束本身不会阻止你传入一个继承自 class 的类型——因为根本不可能有这种类型。











