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类 ...
随机推荐
- java Annotation Demo
Java 1.5引入了annotation,这个功能非常好用,是用c#等语言借鉴过来的一个特性. 首先编译器本身支持一些像overrides,supresswarning之类的注解. Spring,j ...
- 【Android UI设计与开发】7.底部菜单栏(四)PopupWindow 实现显示仿腾讯新闻底部弹出菜单
前一篇文章中有用到 PopupWindow 来实现弹窗的功能.简单介绍以下吧. 官方文档是这样解释的:这就是一个弹出窗口,可以用来显示一个任意视图.出现的弹出窗口是一个浮动容器的当前活动. 1.首先来 ...
- HDU 3667 费用流(拆边)
题意:有n个城市(1~n),m条有向边:有k件货物要从1运到n,每条边最多能运c件货物,每条边有一个危险系数ai,经过这条路的费用需要ai*x2(x为货物的数量),问所有货物安全到达的费用. 思路:c ...
- MongoDB学习(三)数据导入导出及备份恢复
这几天想着公司要用MongoDB,自然就要用到数据导入导出,就自己学习了一下. 在Mongo学习(二)中就讲到了在bin目录下有一些工具,本篇就是使用这些工具进行数据的导入导出及备份恢复. 注意:以下 ...
- CSS3实现几个常用的网页小效果
主题 由于最近比较忙,自己也没有很充裕的时间可以去做比较丰富的分享.今晚我挤出时间来制作这几个很常用的CSS3网页小效果.最近写JS的时间比例比较多,不过我还是比较钟情于CSS3.所以我还是坚持分享一 ...
- poj1144
Network Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 12521 Accepted: 5760 Descript ...
- [Erlang37]error/1 exit/1 exit/2 throw/1的区别
1. error/1 主要是系统用来定义内部错误的: Erlang内建的run time error 一共有10种: function_clause/case_clause/if_clause/bad ...
- Android 中调试手段 打印函数调用栈信息
下面来简单介绍下 android 中的一种调试方法. 在 android 的 app 开发与调试中,经常需要用到打 Log 的方式来查看函数调用点. 这里介绍一种方法来打印当前栈中的函数调用关系 St ...
- C语言 百炼成钢7
//题目19:一个数如果恰好等于它的因子之和,这个数就称为“完数”.例如6=1+2+3.编程找出1000以内的所有完数. #define _CRT_SECURE_NO_WARNINGS #includ ...
- CentOS7 SSH相关
1.查看SSH是否已经安装,命令: rpm -qa |grep ssh 如果列出了openssh-x.x开头的软件名,代表已经安装 如果没有安装,使用命令安装: yum install ssh 2.如 ...