c#引用类型和值类型的理解及具体的区分使用

引用类型和值类型的概念

面向.NET框架的所有语言的数据类型都由.NET框架中的通用系统类型CTS(Common Type System)定义。
• 值类型:存储数据本身
• 引用类型:存储数据的引用(内存地址)

划分

在这里插入图片描述
注意:C#的bool、char和所有数值类型都是由结构体定义的。
系统命名空间中Int32的定义

堆和栈

程序运行时,公共语言运行库 (common language runtime,CLR) 会向操作系统申请内存并进行划分区域,其中就有堆区和栈区。

  • 栈(Stack):
    • 空间小,读取速度快。
    • 用于存储正在执行的方法,分配的空间叫做栈帧。栈帧中存储方法的参数以及变量等数据。方法执行完毕后,对应的栈帧将被清除。
  • 堆(Heap):
    • 空间大,读取速度慢。
    • 用于存储引用类型的数据。
      stack&heap
装箱和拆箱

当值类型的数据转换为引用类型时为装箱,反之为拆箱。

储存
局部变量

• 值类型:声明在栈中,保存在栈中
• 引用类型:声明在栈中,保存在堆中

成员变量

• 值类型:声明在堆中,保存在堆中
• 引用类型:声明在堆中,保存在堆中的另一块空间

分析

(对局部变量存储位置的分析)

值类型的使用特点
    int s1 = 1;
    int s2 = s1;//将s1的值赋给s2
    s1 = 2;
    Console.WriteLine (s2);// 1

这段代码中,因为int是值类型,数据直接保存在栈上,s1s2所在的地址直接保存值(1or2)。
s1 s2并无直接关联。

引用类型的使用特点
    int[] arr1 = new int[] { 1, 2, 3 };
    int[] arr2 = arr1;
    arr1[0] = 6;
    Console.WriteLine (arr2[0]);//6

声明为引用类型的字段在栈中的存放的是数据在堆中的地址new关键字就是在中申请一段内存然后返回此段内存的地址
上例中,在栈中声明数组后在堆区申请了一段内存存放数组的实际数据,并将此数组在堆中的地址存储在声明(arr1)中。
由于arr1存放的是实际数组的地址(引用),将arr1赋值给arr2实际就是把arr1中存放的地址赋值给arr2在栈中的内存;赋值完成之后arr1和arr2指向的就是同一个数组。
由此通过arr1修改数组的值和通过arr2读取数据本质上都是在对同一个数组进行操作。可以认为arr1和arr2是一个数组的两个名字。

string
    string s1 = "man";
    string s2 = s1;
    s1 = "woman";
    Console.WriteLine (s2); //man

C#中,字符串具有不可变性

下图是两个例子,我也很疑惑,暂时先记住使用规则吧。
在这里插入图片描述

	由此留下两个疑问:
	1. clr是怎么区分值类型和引用类型的?
	2. 为什么可以直接把int赋值给object?int不全是由结构体定义的吗?(貌似所有的值类型都可以这么干)

等我以后查到了/学到了再回来填坑吧…

总结

  1. 方法执行在栈中;
  2. 所以在方法中声明的变量都在栈中;
  3. 因为值类型直接存储数据,所以数据存储在栈中;
  4. 又因为引用类型存储数据的引用,所以数据在堆中,栈中存储数据的引用。

核心就是:看改变的是栈上的数据还是堆上的数据

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值