第一次接触是拆箱和装箱的定义:后来就查了查发现了很多问题,后来就百度了一下,发现了一句话印象特别的深刻:值类型是现金,引用类型是存折。这样把书本上那些生硬的话跟现实生活中常见的事物联系起来了。更直白点儿说:值类型就是现金,要用直接用;引用类型是存折,要用还得先去银行取现。
下面言归正传:
一、概念:
1.值类型:(1)在栈中分配内存,在声明时初始化才能使用,不能为null。
(2)超出作用范围系统自动释放内存。
(3)表示实际的数据
2.引用类型:
(1)在堆中分配内存,初始化时默认为null。
(2)通过垃圾回收机制进行回收。
C#中定义的值类型包括原类型(Sbyte、Byte、Short、Ushort、Int、Uint、Long、Ulong、Char、Float、Double、Bool、Decimal)、枚举(enum)、结构(struct)
引用类型包括:类、数组、接口、委托、字符串等。
二、 下面用一段代码更加深入的理解区别(此代码为模仿)
<span style="font-size:18px;"></span><pre name="code" class="html"><span style="font-size:18px;">Public static class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Marry
{
public static void Marryme()
{
Person xiaodong = new Person { Name = "XiaoDong", Age = 25 };
Person dongwife = new Person { Name = "DongWife", Age = 23 };
int age = xiaodong.Age;
xiaodong.Age = 22;
Person guy = dongwife;
dongwife.Name = "buzhidao";
Console.WriteLine("xiaodong's age:\t{0}", xiaodong.Age);
Console.WriteLine(" age'value:\t{0}", age);
Console.WriteLine(" dongwife'value:\t{0}", dongwife.Name);
Console.WriteLine(" guy'name:\t{0}", guy.Name);
}
}</span>
上面这段代码,我们首先创建了一个Person类,包含了Name和Age两个属性,看上面的图片知道,Person类是引用类型,Name也是,但Age则是值类型。接下来我们来看看Marryme方法,其中演示的就是值类型跟引用类型的区别(1)首先,我们声明了两个Person类的实例对象,xiaodong和dongwife,前面提到过,这两个对象都被分配在堆上,而xiaodong和dongwife本身其实只是对象所在内存区域的起始地址引用,换句话说就是指向这里的指针。我们声明对象实例时也顺便分别进行了初始化,首先我们看,xiaodongl对象的值类型成员,我们赋值为25岁,dongwife的Name属性,我们赋值为“Dongwife”。
(2)我们声明一个值类型变量age,直接在初始化时把xiaodong的Age值赋给它,显然,age的值就是25了。但这个时候xiaodong想让自己的年龄改成22岁,刚够法定结婚年龄。然后我们又声明了一个引用类型的guy对象,初始化时就把Dongwife赋给它,他的名字叫“buzhidao”。接下来我们来分别答应出这几个变量的值,看看有什么差别。
细心的人会发现以下几个问题
1、为什么我们改了xiaodong.Age的值,age没跟着变,改了dongwife.Name的值,guru.Name却跟着变了呢?
这就是值类型和引用类型的区别。我们声明age值类型变量,并将xiaodong.Age赋给它,编译器在栈上分配了一块空间,然后把xiaodong.Age的值填进去,仅此而已,二者并无任何牵连,就像复印机一样,只是把xiaodong.Age的值拷贝给age了。而引用类型不一样,我们在声明guy的时候把dongwife赋给它,前面说过,引用类型包含的是只想堆上数据区域地址的引用,其实就是把dongwife的引用也赋给guy了。
问题 | 值类型 | 引用类型 |
内存分配地点 | 分配在栈中 | 分配在堆中 |
效率 | 效率高,不需要地址转换 | 效率低,需要进行地址转换 |
内存回收 | 使用完后,立即回收 | 使用完后,不是立即回收,等待GC回收 |
赋值操作 | 进行复制,创建一个同值新对象 | 只是对原有对象的引用 |
函数参数与返回值 | 是对象的复制 | 原有对象的引用,并不产生新的对象 |
类型扩展 | 不易扩展 | 容易扩展,方便与类型扩展 |
注:1、GC(Garbage Collector,垃圾回收器)是一种自动回收内存的机制,释放已经不再使用的对象的内存空间。
2、堆和堆栈区别:
堆和堆栈是两个不同的概念,在内存中的存储位置也不相同,
堆一般用于存储可变长度的数据,如字符串类型;
堆栈则用于存储固定长度的数据,如整型类型的数据int(每个int变量占用四个字节)。由数据存储的位置可以得知,当把一个值变量赋给另一个值变量时,会在堆栈中保存两个完全相同的值;而把一个引用变量赋给另一个引用变量,则会在堆栈中保存对同一个堆位置的两个引用,即在堆栈中保存的是同一个堆的地址。在进行数据操作时,对于值类型,由于每个变量都有自己的值,因此对一个变量的操作不会影响到其它变量;对于引用类型的变量,对一个变量的数据进行操作就是对这个变量在堆中的数据进行操作,如果两个引用类型的变量引用同一个对象,实际含义就是它们在堆栈中保存的堆的地址相同,因此对一个变量的操作就会影响到引用同一个对象的另一个变量。
小结:这篇文章文字比较多,需要一点一点的推敲。因为之前没有学过堆和栈所以理解起来比较吃力,不过通过总结还是多少懂了那么一点了。如果有更好的理解这方面的知识,希望可以一起讨论。