内容将会持续更新,有错误的地方欢迎指正,谢谢!
拥有更好的学习体验 —— 不断努力,不断进步,不断探索 |
助力快速掌握 面试题 为面试者节省宝贵的学习时间,避免困惑! |
文章目录
一、请简述值类型与引用类型的区别
-
存储位置不同:
值类型的数据存储在栈中(值类型嵌套在引用类型里时,跟随引用类型存储),而引用类型的数据存储在堆中,并且在栈中存储堆内存数据的地址。 -
效率不同:
值类型不需要地址转换,存取快,引用类型需要进行地址转换,因为引用类型的变量存储的的是堆中的实例的地址,存取慢。 -
内存分配时机不同:
值类型声明变量后,不管是否已经赋值,编译器都会为其分配内存,引用类型声明变量后,只在栈中分配一小片内存用于容纳一个地址,而此时并没有为其在堆上分配内存空间,当创建一个实例时,会分配堆上的空间,并把堆上的空间的地址保存到栈上分配的小片空间中。 -
释放方式不同:
存储在栈中的值类型在使用完成后会自动释放,而存储在堆上的引用类型则靠GC进行垃圾回收。 -
继承不同:
值类型隐式派生自System.ValueType,引用类型继承自System.Object。 -
默认值不同:
值类型不能为null,默认初始化为该类型的默认值,引用类型默认初始化为null。 -
参数传递上的不同:
值类型作为参数传递时,传递的是数据,引用类型作为参数传递时传递的是数据的引用。 -
赋值上的不同:
当一个变量赋值给另一个变量时,值类型是会复制一个相同的新的值给另一个变量,引用类型是会将原变量数据的引用给新变量,当改变新对象的数据时也会对原对象照成影响,因为他们的引用是同一个。 -
值类型:
struct、enum、bool、char、byte、sbyte、short、ushort、int、uint、long、ulong、float、double (6类:结构体、枚举、布尔、字符、整型、浮点型) 。 -
引用类型:
class、interface、delegate、string、object、array、list(6类:自定义类,接口、委托、字符串、对象、数组)
二、什么是装箱和拆箱
1、什么是装箱拆箱
装箱就是值类型到引用类型的隐式转换,拆箱就是引用类型到值类型的显示转换。
2、装箱和拆箱的过程
-
装箱过程:
1、在堆上分配一个内存空间,这些内存空间主要用于存储值类型的数据
2、将值类型变量的值复制到堆上新分配的内存空间上
3、将堆上创建的对象的地址返回给引用类型变量 -
拆箱过程:
1、检查已装箱的值类型,确保它是给定值类型的一个装箱值
2、将堆中存储的值拷贝到栈上的值类型实例中
3、 如何避免频繁的装箱拆箱
(1)、通过重载函数:Struct通过重载函数来避免装箱拆箱
struct Test
{
int a;
public override string ToString()
{
return "a的值是:" + a;
}
//如果struct没有重载ToString()方法,就会在struct实例调用它们时先装箱再调用,导致内存块重新分配性能损耗
}
(2)、通过泛型
interface ITest
{
void Change(int a);
}
struct A : ITest