CLR:基元类型、引用类型和值类型
最新更新请访问: http://denghejun.github.io
前言
今天重新看了下关于CLR基元类型的东西,觉得还是有必要将其记录下来,毕竟这是理解CLR成功
之路上的重要一步,希望你也和我一样。
基元类型
编译器直接支持的数据类型称之为基元类型,针对那些程序员自定义的类型而言。所有基元类型
直接映射到FCL(Framework class library)中存在的类型;比如C#中int直接映射到System.
Int32类型,且在编译为IL(中间语言)时,他们将会是一模一样的:
int a=;
System.Int32 a=;
int a=new int();
System.Int32 a=new System.Int32();
至于,为什么我们经常使用的是int这样的简单类型,而不是System.Int32,微软在C#语言规范
(CLS)中有这样的建议:“从风格上说,最好是使用关键字,而不是使用完整的系统类型名称”。
但是使用关键字有时候会使得程序员倍感迷惑,例如int比较没有Int32那样直接的显示这是一个有
符号的32值。
引用类型
任何称之为“类”的类型都是引用类型。引用类型总是从堆上分配内存,C#的new操作符将会返回对
象的内存地址。使用引用类型时必须考虑以下事实;
- 内存必须从托管堆上分配
- 堆上分配的每个对象都有一些额外的成员,它们必须初始化
- 对象中的其他字节总是设为零
- 从托管堆上分配一个对象时,可能强制执行一次垃圾收集操作
很明显,过多的使用引用类型可能会导致应用程序性能显著下降。
引用类型变量的互相赋值只会赋值对象的内存地址,所以指向同一对象的变量在发生改变时实际上影
响的是同一个对象。
值类型
所有值类型又都称之为结构或枚举。值类型在线程栈上分配空间。所有的值类型都直接派生于抽象类
型System.ValueTye,而后者本身又直接从System.Object派生。所有值类型都是密封的(sealed)
,因此,无法被继承,从而无法使用值类型定义新的类型。
值类型变量的互相赋值将会执行一次逐字段的复制。
值类型与引用类型的取舍
将数据类型定义为结构(值类型)需要考虑一下几点:
- 不需要从其他类型继承
- 不需要派生
- 类型实例较小或不作为实参和返回值
- 类型实例不需要做线程同步访问
无法继承和派生是值类型的显著特点,你必须慎重考虑他们。另外,若值类型实例过大,在入参时会
发生复制行为,占用空间;在作为返回值时也将值类型的实例复制到调用者的分配内存中。因为未装箱
的值类型没有同步索引块,所以不能使用Monitor或lock等方法(语句)让多个线程同步对这个对象的
访问。
装箱与拆箱
值类型有两种表现形式:未装箱(unboxed)和已装箱(boxed)形式;引用类型总是处于已装箱模
式。
值类型是一种“轻型”的类型,它不会作为对象在托管堆中分配内存,不会被垃圾回收,也不能通过指针
来引用。但在许多情况下我们需要获取对一个值类型实例的引用:
struct Point
{
public int x,y;
} ArrayList list=new ArrayList();
Point p;
for(int i=;i<;i++)
{
p.x=p.y=i;
list.Add(p); // 将值类型进行装箱,并添加到集合中
}
上面的例子中,由于ArrayList的Add方法需要一个类型为Objec的入参,而我们传入的是值类型Point
,所以这里将发生装箱的操作。所有在值类型转化为引用类型的地方都需要装箱。装箱(boxing)内部
发生的过程如下:
1.在托管堆上分配好内存,大小为值类型所有字段的大小加上引用类型的额外
成员(对象指针和同步块索引)
2.值类型的字段复制到新的堆内存中
3.返回对象的地址
可见,已装箱的值类型的生命周期超过了未装箱的值类型。
另外,值类型在转化为某个接口或调用未重写的基类方法时(所有的值类型都继承System.Object),需
要装箱。因为基类的this希望接受一个指向堆上的一个对象的指针。
拆箱并不是装箱的逆过程:
Point p=(Point)list[];
拆箱在CLR中分两步完成这个操作:
1.获取已装箱的Point对象中的各个Point字段的地址,这个过程就是拆箱(unboxing);
2.将这些字段包含的值从堆中复制到基于栈的值类型实例中(也就是上例中的p)。
所以,拆箱实际上是指一个寻址的过程,拆箱的代价远低于装箱,因为它确实知识一个简单的寻找指针
的过程而已,在这之后才会发生逐字段复制的过程。
CLR:基元类型、引用类型和值类型的更多相关文章
- CLR via C#(02)-基元类型、引用类型、值类型
http://www.cnblogs.com/qq0827/p/3281150.html 一. 基元类型 编译器能够直接支持的数据类型叫做基元类型.例如int, string等.基元类型和.NET框架 ...
- [CLR via C#]引用类型和值类型
一.引用类型与值类型的区别 CLR支持两种类型:引用类型和值类型.引用类型总是从托管堆上分配的,C#的new操作符会返回对象的内存地址.使用引用类型时,必须注意到一些性能问题. 1)内存必须从托管堆上 ...
- 《CLR via C#》读书笔记--基元类型、引用类型和值类型
编程语言的基元类型 编译器直接支持的数据类型称为基元类型.基元类型直接映射到Framework类库中存在的类型.例如:C#中的int直接映射到System.Int32类型.下表给出了C#基元类型与对应 ...
- 《CLR via C#》读书笔记(5)基元类型、引用类型和值类型
5.1 基元类型 编译器直接支持的数据类型称为基元类型(primitive type). 以下4行到吗生成完全相同的IL int a = 0; //最方便的语法 System.Int32 b = 0; ...
- 【CLR Via C#】第5章 基元类型、引用类型、值类型
第二遍看这本书,决定记录一下加深印象. 1,基元类型 什么事基元类型?基元类型是直接映射到FrameWork类库(FCL)中存在的类型,编译器直接支持的数据类型.比如int直接映射到System.In ...
- CLR via C#深解笔记三 - 基元类型、引用类型和值类型 | 类型和成员基础 | 常量和字段
编程语言的基元类型 某些数据类型如此常用,以至于许多编译器允许代码以简化的语法来操纵它们. System.Int32 a = new System.Int32(); // a = 0 a = 1 ...
- <NET CLR via c# 第4版>笔记 第5章 基元类型、引用类型和值类型
5.1 编程语言的基元类型 c#不管在什么操作系统上运行,int始终映射到System.Int32; long始终映射到System.Int64 可以通过checked/unchecked操作符/语句 ...
- 重温CLR(四)基元类型、引用类型、值类型
编程语言的基元类型 编译器直接支持的数据类型称为基元类型(primitive type).基元类型直接映射到framework类型(fcl)中存在的类型. 下表列出fcl类型 从另一个角度,可以认为C ...
- CLR VIA C#: 基元类型、 引用类型 和 值类型
一.基元类型 . 引用类型 和 值类型的区别: 1.基元类型(primitive type):编译器直接支持的数据类型: 基元类型 直接映射到 FCL 中存在的类型. C# 小写是基元类型,例如:st ...
随机推荐
- 支持向量机SVM
SVM(Support Vector Machine)有监督的机器学习方法,可以做分类也可以做回归.SVM把分类问题转化为寻找分类平面的问题,并通过最大化分类边界点距离分类平面的距离来实现分类. 有好 ...
- mysql命令导出导入数据库
命令导出数据库: mysqldump -h[主机所在IP] -u[用户名] -p [要导出的数据库]>[导出的路径//[文件名].sql] 命令导入数据库: 1>首先,我们应该在cmd中进 ...
- jquery版相片墙(鼠标控制图片聚合和散开)
照片墙,简单点说就是鼠标点击小图片时,聚合变成一张大图片:点击大图片时,散开变成小图片.这个是我一年前无意间看到的动画效果(现在已经忘记是哪位大神制作的了,引用了他的图片),刚看到这个很炫的动画超级激 ...
- word20161213
journal queue / 日志队列 journal quota / 日志配额 junction point / 交叉点 KDC, Key Distribution Center / 密钥分发中心 ...
- HFS远程命令执行漏洞入侵抓鸡黑阔服务器
先来科普一下: HFS是什么? hfs网络文件服务器 2.3是专为个人用户所设计的HTTP档案系统,如果您觉得架设FTP Server太麻烦,那么这个软件可以提供您更方便的网络文件传输系统,下载后无须 ...
- PYTHON 写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者
def a2(arg): if len(arg) > 2: del arg[2:] li = [12,13,14,15] a2(li) print(li)
- C# 使用 StructLayoutAttribute 时 C# /C++ 内存空间分配与成员对齐问题
1. 使用场景 公共语言运行时控制数据字段的类或结构在托管内存中的物理布局.但是,如果想要将类型传递到非托管代码,需要使用 StructLayout 属性. 2. 内存分配问题. 如果不显示的设置内存 ...
- EL算术表达式
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...
- hmm
http://www.cnblogs.com/mindpuzzle/p/3653043.html http://en.wikipedia.org/wiki/Viterbi_algorithm http ...
- (2016弱校联盟十一专场10.3) D Parentheses
题目链接 把左括号看成A右括号看成B,推一下就行了.好久之前写的,推到最后发现是一个有规律的序列. #include <bits/stdc++.h> using namespace std ...