C#中值类型和引用类型
本文将介绍C#类型系统中的值类型和引用类型,以及两者之间的一些区别。同时,还会介绍一下装箱和拆箱操作。
值类型和引用类型
首先,我们看看在C#中哪些类型是值类型,哪些类型是引用类型。
值类型:
- 基础数据类型(string类型除外):包括整型、浮点型、十进制型、布尔型。
- 整型(sbyte、byte、char、short、ushort、int、uint、long、ulong )
 - 浮点型(float 和 double )
 - 十进制型(decimal )
 - 布尔型(bool )
 
 - 结构类型(struct)
 - 枚举类型(enum)
 
引用类型:
- class、interface、delegate、object、string、Array
 
默认值
变量的初始化中,都会有一个默认值,在C#中,我们可以通过default关键字去查看某个类型的默认值。
通过default(int)可以看到,int的默认值是0,default(bool)显示布尔类型的默认值是false。
对于所有的引用类型,默认值都会是null。
注意,这里有个特殊的情况就是结构struct,如果对一个结构进行default操作,我们将得到每个结构成员的初始值状态。也就是说,值类型成员赋予值类型的默认值,引用类型成员赋予引用类型的默认值。
简单对比值类型和引用类型
下面,我们通过一个简单的例子看看。假设有一个Point类型,有x和y两个坐标成员。
同样是下面一段代码
Point p1 = new Point(,);
Point p2 = p1;
如果Point类型是通过结构struct实现,那么p2将会是p1的一个副本,也就是说任何一个的修改都不会影响另外一个;如果Point类型是通过类class实现,那么p2和p1的引用值将会指向同一个对象。

为了进一步了解值类型和引用类型,我们需要介绍一下栈和堆这两个基本概念。
栈和堆
当我们在32位系统上运行一个程序的时候,这个程序就会有一个4GB的进程运行空间。我们所要讨论的栈和堆就存放在这个4GB的空间中。
栈和堆的简介
在C#中,栈(Stack)是指调用栈(call stack);堆(Heap)是指托管堆,由.NET垃圾收集器自动管理。
这里就不对栈和堆进行详细的分析了,只是举一个简单的例子来大致描述栈和堆的工作原理。

从图中可以看到,局部变量在栈上的变化(入栈),当函数执行结束后,栈上的空间将会被清理;但是我们在堆上分配的空间始终从在,只能等待GC去帮我们清理不会被引用到的空间。
值类型和引用类型的存放
介绍过栈和堆之后,下面我们看看值类型和引用类型是怎么存放的。
对于值类型的变量,这个变量本身就代表这个值类型的值;但是,对于引用类型的变量,这个引用类型的实例是在托管堆上分配的空间,而这个变量本身只是代表一个指向托管堆实例的引用(指针)。
所以这里,我们可以对值类型和引用类型变量的存储有两个概括:
- 引用类型永远存储在堆里
 - 值类型和引用(指针)永远存储在它们声明时所在的堆或栈里
- 如果一个值类型不是在方法中定义的,而是在一个引用类型里,那么此值类型将会被放在这个引用类型里并存储在堆上
 
 
注意:根据上面第二点概括,可以得到"值类型一定存储在栈中"这个说法是错误的。例如,我们有一个Student类,在这个类中的Age属性是一个值类型,但是这个值类型是存储在Student类实例的空间中,也就是在堆上。
class Student
{
public string Name { get; set; }
public int Age{ get; set; }
}
装箱和拆箱
由于C#中所有的数据类型都是由基类System.Object继承而来的,所以值类型和引用类型的值可以通过显式(或隐式)操作相互转换。
这里,可以将装箱和拆箱描述为:
- 装箱是将值类型转换为引用类型
 - 拆箱是将引用类型转换为值类型
 
装箱/拆箱的内部操作
其实,在装箱和拆箱的过程中都对应一系列的转换,这里就通过下图表示了。

在值类型进行装箱时,生成的是全新的引用对象,这会有时间损耗,也就是造成效率降低。所以在C# 2.0中就引入了泛型来减少装箱操作和拆箱操作消耗。
总结
本文介绍了C#中的值类型和引用类型,以及栈和堆的基本概念。然后分析了值类型和引用类型在栈和堆中的存放。
同时,我们也了解到了:
- 当使用引用类型时,我们是在和指向引用类型的引用(指针)打交道,而不是引用类型本身
 - 当使用值类型时,我们是在和值类型本身打交道
 
C#中值类型和引用类型的更多相关文章
- JavaScript中值类型和引用类型的区别
		
JavaScript的数据类型分为两类:原始类型和对象类型.其中,原始类型包括:数字.字符串和布尔值.此外,JavaScript中还有两个特殊的原始值:null和undefined,它们既不是数字也不 ...
 - JAVA中值类型和引用类型的不同(面试常考)
		
转载:https://www.cnblogs.com/1ming/p/5227944.html 1. JAVA中值类型和引用类型的不同? [定义] 引用类型表示你操作的数据是同一个,也就是说当你传一个 ...
 - C#中值类型和引用类型的差别浅记
		
C#中值类型和引用类型的差别浅记 在C#中,变量的类型分为两种.各自是值类型和引用类型. 值类型的变量直接存储值,说得更详细一些,就是值类型变量在内存中直接存储它们自身 ...
 - C#中值类型和引用类型图解
		
举几个值类型和引用类型的内存配置: 值类型存储在栈中,引用类型堆里: 1,数组 数组是引用类型,但是数组的元素可以是值类型或引用类型 2. 结构 结构是值类型,简略的看个例子 struct sampl ...
 - java中值类型和引用类型的区别
		
[定义] 引用类型表示你操作的数据是同一个,也就是说当你传一个参数给另一个方法时,你在另一个方法中改变这个变量的值,那么调用这个方法是传入的变量的值也将改变. 值类型表示复制一个当前变量传给方法,当你 ...
 - JavaScript中值类型与引用类型
		
JavaScript中的变量类型有哪些? 值类型:字符串(string).数值(number).布尔值(boolean).null.undefined 引用类型:对象(Object).数组(Array ...
 - .net中值类型、引用类型理解的c#代码示例
		
下面是以前在公司的时候给别人讲解值类型.引用类型时创建的c#代码示例,从实际使用时的角度出发,对于初学者还是很有帮助的.这里并没有深入讲解值类型包含引用类型成员时(如struct)在内存中的存放情况等 ...
 - JS中值类型和引用类型
		
一.值类型 例子: var a=10; var b=a; a=20; console.log(b); 例子中,将a的值赋给了b,b=10,然后改变a的值不会影响b的值,a和b是独立的两份,互不影响. ...
 - C#中值类型与引用类型通俗理解
		
关于值类型和引用类型已经有很多人写了很多文章,但是很多人也只是停留在字面上的理解,如果采用一种通俗的方法来解释,想必很多人都会理解.我们都知道值类型存储在栈上,引用类型存储在堆上,引用类型都是xxx类 ...
 
随机推荐
- 记一次Web应用CPU偏高
			
LZ开发的一个公司内部应用供查询HIVE数据使用.部署上线后总是会出现CPU偏高的情况,而且本地测试很难重现.之前出现几次都是通过直接重启后继续使用,因为是内部使用,重启一下也没有很大影响(当然,每次 ...
 - spring 容器加载完成后执行某个方法
			
理论 刚好再开发过程中遇到了要在项目启动后自动开启某个服务,由于使用了spring,我在使用了spring的listener,它有onApplicationEvent()方法,在Spring容器将所有 ...
 - O(N)时间的排序
			
题目:某公司有几万名员工,请完成一个时间复杂度为O(n)的算法对该公司员工的年龄作排序,可使用O(1)的辅助空间. 要注意分析题目,一般排序要么是O(n^2),要么是O(nlogn).但这里题目特别强 ...
 - excel vba 当cell的值变化时 进行判断操作
			
示例效果: ----------- 在excel的sheet1中, 当A列的值 大于100时 ,其对应B列背景显示红色,C列显示"有数据" 否则,B列背景色正常,C列清空相应的数据 ...
 - Ubuntu 14.04 单机安装 CEPH
			
0.如果先前安装过ceph,则先卸载 sudo stop ceph-all //停止所有CEPH进程 ceph-deploy uninstall [{ceph-node}] //卸载所有ceph程序 ...
 - 首个攻击该Mac OS系统的恶意软件——KeRanger
			
首个攻击该Mac OS系统的恶意软件——KeRanger 曾几何时,苹果操作系统一度被人认为是最安全的操作系统.然而近几年,针对苹果系统的攻击日益增多,影响范围也越来越大.无独有偶,近日,苹果Mac ...
 - 孙鑫视频学习:对第10章设置线宽时为什么不调用UpDateData(TRUE)的理解
			
在第10章10.2.1小节中,首先分别对视图类和对话框类添加了一个名为m_nLineWidth的int型变量,再将用户在CSetting dlg对话框的edit控件中输入的线宽值记录在dlg.m_nL ...
 - J2EE笔记2
			
1. 部署并启动 tomcat 服务器.1). 解压 apache-tomcat-6.0.16.zip 到一个非中文目录下2). 配置一个环境变量. java_home(指向 JDK 安装的根目录) ...
 - codeforces 477B B. Dreamoon and Sets(构造)
			
题目链接: B. Dreamoon and Sets time limit per test 1 second memory limit per test 256 megabytes input st ...
 - MySQL数据库学习笔记(八)----JDBC入门及简单增删改数据库的操作
			
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...