谈一谈值类型与引用类型和装箱与拆箱

值类型与引用类型

首先说一说什么是值类型和引用类型

1
2
值类型直接存储其值。
引用类型存储对值的引用。

粗俗点儿翻译的就是值类型就是现金,要用直接用;引用类型是存折,要用还得先去银行取现。

衍生出几个问题:

1
2
3
1.为什么能直接直接用
2.引用类型怎么引用的
3.有啥区别

问题1 为什么值类型的能直接用

基础扎实的同学知道。栈空间是某个进程启动的时候所内置的内存空间,我们经常听到的比如局部变量。这类型信息就存在栈当中,所以可以直接使用。但是栈的空间比较小。如果有其他需求我们只能放到堆内存当中。

问题2 引用类型怎么引用的

如图,我们创建Name类就是在堆内存中,而我们如果需要使用。实例化以后。如下图所示

obj这个变量存储的东西只是Name对象的地址.(这个引用过程就是传说中的指针)

问题3 有啥区别

1
2
3
4
5
6
7
8
值类型通常被人们称为轻量级的类型,因为在大多数情况下,值类型的的实例都分配在线程栈中,因此它不受垃圾回收的控制,缓解了托管堆中的压力,减少了应用程序的垃圾回收的次数,提高性能。

所有的引用类型的实例都分配在托管堆上,c#中new操作符会返回一个内存地址指向当前的对象。所以当你在创建个一个引用类型实例的时候,你必须要考虑以下问题:

> 内存是在托管堆上分配的
> 在分配每一个对象时都会包含一些额外的成员(类型对象指针,同步块索引),这些成员必须初始化
> 对象中的其他字节总是设为零
> 在分配对象时,可能会进行一次垃圾回收操作(如果托管堆上的内存不够分配一次对象时)

装箱与拆箱

简单解释

1
2
3
装箱 就是把“值类型”转换成“引用类型”(Object);

拆箱 就是把“引用类型”转换成“值类型”;

举个例子

1
2
3
4
5
6
7
8
//装箱 boxing
int i = 3 ; //分配在栈上
object o = i ;//隐式装箱操作,int i 在堆上
object b = (object)i ; //显示装箱操作
//拆箱 unboxing
int j = (int) o ;//显示拆箱(将对象o拆箱为int类型)

int k = b ;//error!!, 不能隐式拆箱

总结

1
2
3
4
5
值类型和引用类型理解透彻后,我们知道C#里面是值传递,但是有些变量是引用类型的,在传递和拷贝时需要特别注意。方法传递参数时加上ref(out),为引用传递参数。

值传递仅仅传递的是值,不影响原始值。

引用传递,传递的是内存地址,修改后会改变内存地址对应储存的值

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!