C#基础 引用类型 和 值类型

内存中存在2大区域——堆,栈;

堆栈概念

栈在编译时分配好内存空间

随程序运行情况动态分配内存的大小

引用类型 和 值类型

值类型

值类型 是在中分配的一个内存空间,诸如int,float,char都是值类型,值类型的数据就写在栈分配的那一个内存空间内(但这话说得不绝对,后面我细细道来)

引用类型

引用类型 是先在中分配一个内存空间,然后在堆中分配一个内存空间,把数据写入堆的空间中,再把这块堆的地址赋给栈空间,换种方法说:栈中存的是一个指针,指向堆中的某个地址;而堆中那块地址存储的才是真实值。

编程时可能遇到的问题

  • 类中的基础类型的值也是写在堆中的
    // 定义一个类
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    
    Student类定义一个对象,主程序中尝试修改这个对象
    static void Main(string[] args)
        {
            Student s2 = new Student { Id = 2,Name = "2"};
            Student s3 = s2;
    		s3.Id = 10;
            Console.WriteLine($"{s3.Id} {s2.Id}");// 打印结果10 10
            Console.ReadLine();
        }
    
    看,Id是值类型int,反而修改了s3Ids2的也跟着变了;这就说明即便是值类型,在类对象中也是存储在堆中而非栈中的。单独使用才在栈中存在(如下代码示例)
    static void Main(string[] args)
    {
        int i = 10;
    	int j = i;
    	i = 0;
        Console.WriteLine($"{i} {j}");// 打印结果0 10,j的数值没有受到i改变的影响
        Console.ReadLine();
    }
    
  • 浅拷贝类时修改其中一个的某一属性后,另一个类变化
    这种情况的BUG是最常见的,举个例子
    // 定义一个类
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    
    static void Main(string[] args)
        {
            Student s2 = new Student { Id = 2,Name = "2"};
            Student s3 = s2;
            s3.Name = "a";
            Console.WriteLine($"{s3.Name} {s2.Name}");// 打印结果a a
            Console.ReadLine();
        }
    
    看出问题没?s3是浅拷贝s2来的,s3后面改name属性,结果s2也跟着改了。因为s3,s2都定义在栈中,两者存储的地址却是指向同一堆区域,这就是浅拷贝——牵一发动全身!

ps:分清楚C#中的引用类型 和 值类型 有利于在今后编程中快速定位一些隐藏的BUG

posted @ 2022-11-26 11:43  勤匠  阅读(36)  评论(0编辑  收藏  举报