xqqlyx

C#值类型和引用类型的区别-程序验证

区别

值类型分配在栈上(如果不在栈帧当中声明),如果是类的属性、数组、被装箱、放在闭包中那就是在堆上。
引用类型分配在堆上,栈中存的是引用变量,引用变量的值是堆上的地址。
GC 只管堆,不管栈
栈:自动释放
堆:GC 回收

值类型

数据直接存在声明的位置
方法内 → 栈
类 / 数组 / 装箱 → 堆
和大小无关!

引用类型

真实数据 → 永远在堆
栈上只存引用(地址)
引用变量 = 指向堆的指针

    static void Main()
    {
        // 值类型
        int a = 100;
        cwl($"{nameof(a)} 栈地址: {(long)&a:X}");

        // 引用类型变量(栈)
        string str = "hello";
        cwl($"str 变量栈地址: {(long)&str:X}");

        // 引用类型对象(堆)
        fixed (char* p = str)
        {
            cwl($"str 堆真实地址: {(long)p:X}");
        }

        // 栈里存的就是堆地址
        long* pStr = (long*)&str;
        cwl($"栈中存储的堆地址: {*pStr:X}");
    }

    static void cwl(string msg) => Console.WriteLine(msg);
}

输出结果

PixPin_2026-05-11_14-44-48
仅从地址是无法判断的 但是分配在栈中的地址一般是相邻几个字节的
而分配在堆中的地址有跳变、巨大、不连续的特征。

结果分析

栈上
43A5D7EE00:str 变量本身的地址(栈),里面存着 21180101DB0(堆对象地址)
43A5D7EE08:int a 变量的地址(栈),里面存着 100 这个值
堆上
21180101DB0:string 对象的起始地址(对象头、长度信息)
21180101DBC:string 里 char 数组的起始地址(也就是你用 fixed 拿到的地址)

posted on 2026-05-11 14:00  惜清千流云汐  阅读(21)  评论(0)    收藏  举报