【CLR Via C#】第5章 基元类型、引用类型、值类型
第二遍看这本书,决定记录一下加深印象。
值类型可以存储在堆和栈上,它是局部变量时存储在栈上,如果值类型是作为类的一个属性,那么就会存储在堆上;
引用类型有两块内存,一块存储引用地址(栈上),一块存储实际的对象(堆上)。
1,基元类型
什么事基元类型?基元类型是直接映射到FrameWork类库(FCL)中存在的类型,编译器直接支持的数据类型。比如int直接映射到System.Int32类型,就像是添加了using应用:using sbyte=System.SByte.
| C#基元类型 | FCL类型 | 说明 |
| sbyte | System.SByte | 有符号8位 |
| byte | System.Byte | 无符号8位 |
| short | System.Int16 | 有符号16位 |
| ushort | System.UInt16 | 无符号16位 |
| int | System.Int32 | 有符号32位 |
| uint | System.UInt32 | 无符号32位 |
| long | Syetem.Int64 | 有符号64位 |
| ulong | System.Int64 | 无符号64位 |
| char | System.Char | 16位Unicode字符 |
| float | System.Single | 32位浮点值,即带小数 |
| double | System.Double | 64位浮点值 |
| bool | System.Boolean | True/False |
| decimal [英]'desɪml | System.Decimal | 128位高精度浮点值 |
| string | System.String | 字符数组 |
| object | System.Object | 所有类型的基类 |
| dynamic | System.Object |
对于CLR,dynamic和Object完全一致 |
基元类型只有在数量级别小转大的时候可以隐式转换,数量级别大转小的时候必须显示的转换,如下:
Int32 i=1; Int64 l=i; Single s=i; -----隐式转换
Byte b=(Byte)i; Int16 v=(Int16)i; -----显示转换
因为数量级别大转小可能会造成内存溢出,需要用到checked喝unchecked,
使用checked发生溢出时会抛出OverFlowEception异常;
unchecked允许发生溢出;
2 引用类型和值类型
1,为什么会有引用类型和值类型
因为引用类型每一次使用的时候会进行一次内存分配,非常影响程序性能。值类型一般在线程栈上分配,值类型不受垃圾回收器的控制,缓解了托管堆中的压力,减少了一个应用程序在其生存周期内需要进行回收的次数。值类型用 struct来声明。
2.什么时候用值类型
1,类型十分简单,成员值不会被修改,建议标记为readonly。
2,不需要从其他任何类型继承。
3,也不会派生出其他类型。
4,类型实例占用小,小于16个字节,大于16个字节时不作为参数传递,也不会被方法返回。
老赵有一篇经典的struct用法的文章:http://blog.zhaojie.me/2013/04/dont-go-half-way-of-preventing-boxing.html
3.值类型与引用类型的不同
| 值类型 | 引用类型 |
| 有2中表示形式:未装箱和已装箱 | 总是处于已装箱状态 |
|
从System.ValueType派生,由于性能问题,定义值类型时候 需要重写Equals和GetHashCode方法 |
从System.Object派生 |
|
不能将值类型作为基类,所以不能写虚方法,不能是抽象方法 ,所有方法都隐式地为密封方法 |
可以继承和派生 |
| 所有成员初始化为0(可空除外) | 默认值为Null,调用抛出NullReferenceException异常 |
| 值类型赋值时会逐字段赋值 | 引用类型赋值时赋给内存指针 |
| 值类型赋值后自成一体,操作不会受影响 | 引用类型引用的是同一对象,操作会受影响 |
|
值类型不在堆上分配,一旦实例方法不处于活动状态,分配的 存储就会被释放,不需要考虑垃圾回收 |
由GC回收,需要考虑垃圾回收机制。 |
4,值类型的拆箱和装箱
1. 装箱过程?
装箱:将值类型转换为引用类型。当我们把值类型参数传递给需要引用类型参数的方法时,会自动进行装箱操作。过程如下:
- 从托管堆为要生成的引用类型分配大小。大小为:值类型实例本身的大小+额外空间(方法表指针和SyncBlockIndex)。
- 将值类型字段拷贝到刚刚分配的内存中。
- 返回托管堆中新分配内存的地址。也就是指向对象的引用。
2. 拆箱过程?
拆箱:获取指向对象中包含的值类型部分的指针。一般拆箱之后会进行字段拷贝操作,两个操作加起来才是真正与装箱互反的操作。过程如下:
- 如果引用为Null,则抛出NullReferenceException异常。
- 如果引用对象不是一个期望值类型的已装箱对象,会抛出InvalidCastException异常。
- 返回一个指向包含在已装箱对象中值类型部分的指针。
3. 实例
- 拆箱的转型结果必须是它原来未装箱时的类型。
public static void Main() {
Int32 x = 5;
Object o = x; // 装箱
Int16 y = (Int16) o; // 拆箱,抛出InvalidCastException异常
}
修正:Int16 z=(Int16)(Int32)o;//拆箱成功
- 这段代码进行了几次装箱?
public static void Main() {
Int32 v = 5; // 创建值变量
Object o = v; // 装箱
v = 123; // Changes the unboxed value to 123
Console.WriteLine(v + ", " + (Int32) o); // Displays "123, 5" ,装箱两次
}
上面的代码进行了3次装箱,最后一行中v被装箱为引用类型,o首先被拆箱然后再装箱为引用类型。
这一段来自小静:http://www.cnblogs.com/janes/archive/2011/07/04/2097540.html
5,dynamic基元类型
这一段发布的时候自己丢失了,运行时绑定,由dynamic对象的类型来实际决定具体执行的操作!
using System;
internal static class DynamicDemo{
public static void Main(){
for(int i=;i<;i++){
dynamic arg=i==?(dynamic):(dynamic)"A";
dynamic result=Plus(arg);
M(result); //这里会自动根据dynamic是什么类型调用相应的方法。
}
}
private static dynamic Plus(dynamic arg){
return arg+arg;
}
privaye static void M(Int32 a){
Console.WriteLine("M(Int32)"+a);
}
privaye static void M(String a){
Console.WriteLine("M(String)"+a);
}
}
【CLR Via C#】第5章 基元类型、引用类型、值类型的更多相关文章
- [Clr via C#读书笔记]Cp5基元类型引用类型值类型
Cp5基元类型引用类型值类型 基元类型 编译器直接支持的类型,基元类型直接映射到FCL中存在的类型. 作者希望使用FCL类型名称而避免使用关键字.他的理由是为了更加的清晰的知道自己写的类型是哪种.但是 ...
- <NET CLR via c# 第4版>笔记 第5章 基元类型、引用类型和值类型
5.1 编程语言的基元类型 c#不管在什么操作系统上运行,int始终映射到System.Int32; long始终映射到System.Int64 可以通过checked/unchecked操作符/语句 ...
- CLR via C#(02)-基元类型、引用类型、值类型
http://www.cnblogs.com/qq0827/p/3281150.html 一. 基元类型 编译器能够直接支持的数据类型叫做基元类型.例如int, string等.基元类型和.NET框架 ...
- C#中的基元类型、值类型和引用类型
C# 中的基元类型.值类型和引用类型 1. 基元类型(Primitive Type) 编译器直接支持的类型称为基元类型.基元类型可以直接映射到 FCL 中存在的类型.例如,int a = 10 中的 ...
- 《CLR via C#》读书笔记--基元类型、引用类型和值类型
编程语言的基元类型 编译器直接支持的数据类型称为基元类型.基元类型直接映射到Framework类库中存在的类型.例如:C#中的int直接映射到System.Int32类型.下表给出了C#基元类型与对应 ...
- CLR:基元类型、引用类型和值类型
最新更新请访问: http://denghejun.github.io 前言 今天重新看了下关于CLR基元类型的东西,觉得还是有必要将其记录下来,毕竟这是理解CLR成功 之路上的重要一步,希望你也 ...
- 《CLR via C#》读书笔记(5)基元类型、引用类型和值类型
5.1 基元类型 编译器直接支持的数据类型称为基元类型(primitive type). 以下4行到吗生成完全相同的IL int a = 0; //最方便的语法 System.Int32 b = 0; ...
- CLR via C#深解笔记三 - 基元类型、引用类型和值类型 | 类型和成员基础 | 常量和字段
编程语言的基元类型 某些数据类型如此常用,以至于许多编译器允许代码以简化的语法来操纵它们. System.Int32 a = new System.Int32(); // a = 0 a = 1 ...
- 重温CLR(四)基元类型、引用类型、值类型
编程语言的基元类型 编译器直接支持的数据类型称为基元类型(primitive type).基元类型直接映射到framework类型(fcl)中存在的类型. 下表列出fcl类型 从另一个角度,可以认为C ...
随机推荐
- Sql Server 保留几位小数的两种做法
数据库里的 float momey 类型,都会精确到多位小数.但有时候 我们不需要那么精确,例如,只精确到两位有效数字. 1. 使用 Round() 函数,如 Round(@num,2) 参数 2 ...
- Hibernate创建hqll时报错
Hibernate 问题,在执行Query session.createQuery(hql) 报错误 出错截图: 这条语句在java运行环境下,直接连数据库不出错,如果在hiberante,strut ...
- Collection 集合类
ArrayList: 基于动态数组的List 它有两个重要的变量,size为存储的数据的个数.elementData 数组则是arraylist 的基础,因为他的内部就是通过这个数组来存储数据的. p ...
- July 5th, Week 28th Tuesday, 2016
If you smile when no one else is around, you really mean it. 独处的时候你的笑容才是发自内心的笑容. Human beings are so ...
- SQL错误级别 状态 怎么定义
关于SQL Server的错误严重性级别的说明,强烈认真看一下下面的两个链接 脱机帮助 ms-help://MS.SQLCC.v9/MS.SQLSVR.v9.zh-CHS/sqlerrm9/html/ ...
- Delphi线程基础知识
参考http://blog.chinaunix.net/uid-10535208-id-2949323.html 一.概述 Delphi提供了好几种对象以方便进行多线程编程.多线程应用程序有以下几方面 ...
- 11g 使用rman duplicate复制数据库,创建辅助实例
一,创建所需目录 1)创建审计文件目录 PROD1@dbrac1 /dsg/oracle11$ cd $ORACLE_BASE/admin PROD1@dbrac1 /u01/app/oracle/a ...
- c++ 左值右值 函数模板
1.先看一段代码,这就是一种函数模板的用法,但是红色的部分如果把a写成a++或者写成一个常量比如1,都是编译不过的,因为如果是a++的话,实际上首先是取得a的 值0,而0作为一个常量没有地址.写成1也 ...
- POJ1351 Number of Locks(数学)
截至写博客为止,貌似这是网上第一个采用数学公式来处理的. 网上的题解都是DFS或是动态规划,但感觉可以推公式直接用数学的方法处理,想了好久,终于推出公式. 题意:一个长度为n的由数字1,2,3,4 组 ...
- 攻城狮在路上(壹) Hibernate(十一)--- 映射实体关联关系
本文以Customer和Address类的关系为例说明一对一关联映射:以Category和Item类的关系说明多对多关联关系.一.映射一对一关联: 分两种情况:按照外键映射和按照主键映射.这两种方式的 ...