关于值类型和引用类型的区别

C#数据类型分为两大类:值类型(数据存放在栈stack)和引用类型(数据存放在堆heap中,地址存放在栈stack)。下图是列举了两种数据类型的数

值类型变量声明后,不管是否已经赋值,编译器为其分配内存。声明一个引用类时,

只在栈中分配内存,用于存放地址,而并没有为其分配堆上的内存空间。

 

值类型与引用类型使用区别:

本部分主要以自己编写程序来体验两者区别。

对象的传递:

 输出结果:

将值类型的变量赋值给另一个变量,会执行一次赋值,赋值变量包含的值;

将引用类型的变量赋值给另一个引用类型变量,它复制的是引用对象的内存地址,在赋值后就会多个变量指向同一个引用对象实例。

 参数按值传递:

输出结果:

对于值类型(stu1),传递的是该值类型实例的一个副本,因此原本的值stu1并没有改变;

对于引用类型(Student stu2),传递是变量stu2的引用地址(即stu2对象实例的内存地址)拷贝副本,因此他们操作都是同一个stu2对象实例。

参数按引用传递:

输出结果:

不管是值类型还是引用类型,可以使用refout关键字来实现参数的按引用传递。refout关键字告诉编译器,方法传递的是参数地址,而非参数本身。

在按引用传递时,方法的定义和调用都必须显式的使用refout关键字,不可以省略,否则会引起编译错误

注:string与一般引用类型有区别。以下是我对string与其他引用类型进行比较,发现的不同,所编写的程序代码

 String

显示结果:

数组:

显示结果:

结论

string字符串,一开始s1地址指向是hello world,因为s2=s1,所以s2地址也同样指向hello world

s1再次赋值hello Yeebo时,堆中就会开辟出数据hello Yeebo,而且hello world没有消失,没有被覆盖。s1地址就指向hello Yeebos2地址还是原来的hello world

在引用类型数组上,一开始s1s2的地址都指向{1,2,3}

当给S1进行数据更改时,由于是引用类型,所以在{123}上面进行更改,就会对S2进行覆盖

装箱和拆箱:

装箱和拆箱是值类型和引用类型之间的相互转换。

装箱是值类型向引用类型转换时发生的,拆箱是引用类型向值类型转换时发生的。

装箱是隐式的,拆箱是显式的。如下图代码。

结果:

注:对于拆箱存在单词或汉字等转换为int的,这个过程是可能会报错的, Convert.ToInt32()是不可行的,如下图。

 

结果:

需要使用int.TryParse(),才不报错,如下图。

结果:

个人总结:

值类型有更好的效率,但不支持多态,适合用作存储数据的载体。而引用类型支持多态,适合用于定义程序的行为。

引用类型可以派生新的类型,而值类型不能。

 

posted @ 2019-06-27 16:15  KamChuen  阅读(9265)  评论(2编辑  收藏  举报