## 一、核心本质区别值类型存储在栈(Stack)中变量内存里直接存放数据本身引用类型真实数据存放在堆(Heap)栈中只存放堆数据的内存地址引用。口诀**值存栈、存本体引用栈存地址、堆存内容**## 二、包含哪些类型### 1. 值类型全部派生System.ValueType1. 简单值byte/sbyte/short/ushort/int/uint/long/ulong/float/double/decimal/bool/char2. 枚举enum3. 结构体struct包括内置DateTime 注意**struct是值类型class是引用类型**### 2. 引用类型派生System.Object1. string字符串、数组[]2. 自定义class类、接口interface、委托delegate## 三、赋值差异重中之重### 1值类型赋值拷贝一份全新数据int b a; → 在栈新开空间复制数值**两个变量完全独立改一个互不影响**csharpint a 10;int b a;b 99;//a仍10不受b修改### 2引用类型赋值拷贝地址共用堆里同一份数据Person p2 p1; → p1、p2栈中存同一个堆地址**指向同一个堆对象改成员互相影响**csharpclass Person { public int Age; }Person p1 new Person();p1.Age 18;Person p2 p1;p2.Age 30;//p1.Age也变成30## 四、方法传参区别值传递默认规则### 1. 值类型默认传值传副本方法内修改不影响外部原变量csharpstatic void Test(int num) { num 100; }int n 10;Test(n);//n还是10### 2. 引用类型默认传值传【地址副本】地址不变可修改堆里对象内容csharpstatic void Change(Person p) { p.Age 99; }Person per new Person() { Age 10 };Change(per);//per.Age 99被修改 误区引用类型不是传引用是**传引用地址的值**## 五、string特殊特例引用类型但表现像值类型1. string是class引用类型但**字符串不可变**2. 一旦赋值修改会在堆新建字符串原字符串不改动csharpstring s1 abc;string s2 s1;s2 123;//s1不变依旧abc## 六、装箱拆箱值↔引用转换- **装箱值类型 → object(引用)**栈数据复制到堆返回堆地址csharpint a 5;object obj a; //装箱- **拆箱object → 值类型**从堆取出数据放回栈必须强制转换csharpint b (int)obj;//拆箱## 七、ref/out 关键字强行改成按地址传递ref/out不管值/引用类型传递**变量本身地址**方法内修改直接改原变量csharpstatic void Add(ref int x) { x 10; }int num 5;Add(ref num);//num15## 八、精简背诵总结1. **值类型栈存实体赋值克隆传参副本改参不改原值**2. **引用类型栈存地址、堆存实体赋值共用对象传参可修改堆内数据**csharpConsole.ReadKey();