《CLR via C#》读书笔记--基元类型、引用类型和值类型
编程语言的基元类型
编译器直接支持的数据类型称为基元类型。基元类型直接映射到Framework类库中存在的类型。例如:C#中的int直接映射到System.Int32类型。下表给出了C#基元类型与对应的FCL类型

C#规范中写道从风格上说,最好是使用关键字,而不是使用完整的系统类型名称,但作者认为最好使用FCL类型名称
许多开发人员纠结于到时使用
string还是String。由于C#的string关键字直接映射到System.String,所以两者没有区别。有些人说应用程序在32位操作系统运行,int代表32位整数;在64位系统运行,int代表64位系统。这是错误的。C#的int始终映射到System.Int32所以始终代表32位系统。
C#对操作结果总是进行截断,而不是向上取整。
除了转型,基本类型还能写成字面值,就是类型本身的实例。
Console.WriteLine(123.ToString()+456.ToString()); //123456
编译器在编译时就能完成表达式求值,从而增强应用程序性能。
checked和unchecked基元类型操作
C#通过提供checked和unchecked操作符来提供这种灵活性。以下为使用了unchecked操作符的例子:
Uint32 invalid = unchecked(UInt32)(-1);// OK
以下使用了checked操作符;
Byte b = 100;
b =checked((Byte)(b+200)); // 抛出OverflowException异常
也可以这样使用:把需要检查的放到一个语句块中
checked{
Byte b = 100;
b = (Byte)(b+200);
}
建议:
- 尽量使用有符号数值类型,而不是无符号数值类型。这允许编译器检查更多的上溢、下溢错误。
- 写代码时,如果代码可能发生你不希望的溢出,就把这些代码放到
checked语句中。同时捕捉OverflowException异常,得体的从错误中恢复。 - 写代码时,将允许发生溢出的代码放到
unchecked块中,比如在计算校验和时。
引用类型和值类型
CLR支持两种类型:引用类型和值类型。引用类型从托管堆分配,C#的new操作符返回对象的内存地址--即指向对象数据的地址。使用引用类型必须清楚以下四个事实
- 内存必须从托管堆分配
- 堆上分配的每个对象都有一些额外成员,这些成员必须初始化
- 对象中的其它字节总是设为零
- 从托管堆分配对象时,可能强行执行一次垃圾回收。
使用值类型能缓解托管堆的压力
任何称为类的类型都是引用类型,如System.Exception、System.IO.FileStream类等。所有值类型都被称为结构或枚举,如System.Int32结构、Boolean结构、Decimal结构、System.TimeSpan结构等。所有结构都是System.ValueType的直接派生类。System.ValueType又直接从System.Object派生。所有枚举从System.Enum派生,后者从System.ValueType派生。
演示引用类型和值类型的区别

引用类型和值类型让我想起了报纸和网址的区别。使用引用类型就像给了别人一个网址,你在这边修改数据,别人看到的也会修改。而值类型的话更像是给了别人一份报纸的拷贝,你在这边修改,只是像在报纸上做笔记,别人不能看到修改。有些不是很恰当,看上面的例子就会理解了。
如果使用new操作符,C#会认为实例已被初始化:
SomeValue v1 = new SomeValue();
Int32 a = v1.x;//可以通过编译,v1已被初始化为0
而如果
SomeValue v1;
Int32 a = v1.x;//使用了可能未赋值的字段x
对于许多值类型,我们都建议将全部字段标记为readonly
值类型和引用类型的区别:
- 值类型有两种形式:
未装箱和已装箱,引用类型总是处于已装箱模式 - 值类型重写了
Equals和GetHashCode方法。由于这个默认实现存在性能问题,在定义自己的值类型时,应该重写Equals和GetHashCode方法,并提供他们的显示实现 - 值类型能不应引入任何虚方法,不能是抽象的方法
- 引用类型变量中包含
堆中对象的地址,变量创建时会被初始化为null,表明当前不是有效对象。试图使用null引用类型会跑出NullReferenceException异常,相信初学者会经常遇到。 - 值类型复制会逐字段的复制,引用类型复制只复制内存地址
- 两个或多个引用变量可能引用堆中同一对象,而值类型不会,它自成一体。
值类型的装箱和拆箱
public static void Go() {
ArrayList a = new ArrayList();
Point p; // Allocate a Point (not in the heap).
for (Int32 i = 0; i < 10; i++) {
p.x = p.y = i; // Initialize the members in the value type.
a.Add(p); // Box the value type and add the
// reference to the Arraylist.
}
}
// Declare a value type.
private struct Point { public Int32 x, y; }
point是值类型,添加到ArrayList中要发生装箱,造成性能损失。
装箱时要发生的事情:
- 在托管堆中分配内存。
- 值类型的字段赋值到新分配的内存
- 返回对象地址,现在改地址是对象引用,值类型成了引用类型。
注意:FCL现在包含一组新的泛型集合集。应该使用List而不是ArrayList。好处有:泛型集合类允许开发人员使用值类型时不需要对集合中的项进行拆箱和装箱(最重要);增强了编译时的类型安全性等等
拆箱的步骤:
- 获取已装箱Point对象中的各个Point字段的地址。
- 将字段包含的值复制到基于栈的值类型空间中。
第五章内容还剩下一半,明天发。顺便发下我的博客网址L:www.kuiblog.com,谢谢。一起交流
《CLR via C#》读书笔记--基元类型、引用类型和值类型的更多相关文章
- Clr Via C#读书笔记----基元线程同步构造
线程文章:http://www.cnblogs.com/edisonchou/p/4848131.html 重点在于多个线程同时访问,保持线程的同步. 线程同步的问题: 1,线程同步比较繁琐,而且容易 ...
- 2019.03.21 读书笔记 基元类型的Parse与TryParse 性能与建议
Parse转换失败时会抛出异常,耗损性能,如果转换成功,则与TryParse无差异.查看源码,tryparse的代码更多一些,在失败时,反而性能更优,主要是抛出异常耗损了性能.所以在不确定是用Tryp ...
- 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#》读书笔记(5)基元类型、引用类型和值类型
5.1 基元类型 编译器直接支持的数据类型称为基元类型(primitive type). 以下4行到吗生成完全相同的IL int a = 0; //最方便的语法 System.Int32 b = 0; ...
- CLR via #C读书笔记三:基元类型、引用类型和值类型
1.一些开发人员说应用程序在32位操作系统上运行,int代表32位整数:在64位操作系统上运行,int代表64位整数.这个说法是完全错误的.C#的int始终映射到System.Int32,所以不管在什 ...
- [Clr via C#读书笔记]Cp5基元类型引用类型值类型
Cp5基元类型引用类型值类型 基元类型 编译器直接支持的类型,基元类型直接映射到FCL中存在的类型. 作者希望使用FCL类型名称而避免使用关键字.他的理由是为了更加的清晰的知道自己写的类型是哪种.但是 ...
- 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操作符/语句 ...
随机推荐
- 11.21 if条件语句 年月日执行判断
<script language="javascript"> var nian=prompt("输入一个年份","") if(n ...
- Python程序员的进化史
各种程序员所写的阶乘算法代码 # -*- coding: utf-8 -*- #新手程序员(递归) def factorial(x): if x == 0: return 1 else: return ...
- hdu-1856-More is better
More is better Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 327680/102400 K (Java/Others) ...
- Nginx详解-服务器集群
Nginx是什么 代理服务器:一般是指局域网内部的机器通过代理服务器发送请求到互联网上的服务器,代理服务器一般作用在客户端.应用比如:GoAgent,FQ神器. 一个完整的代理请求过程为:客户端首先 ...
- GJM:C# WinForm开发系列 - DataGridView 使用方法集锦 [转载]
1.DataGridView实现课程表 testcontrol.rar 2.DataGridView二维表头及单元格合并 DataGridView单元格合并和二维表头.rar myMultiColHe ...
- Comparable与Comparator的区别
Java的Comparator和Comparable当需要排序的集合或数组不是单纯的数字型时,通常可以使用Comparator或Comparable,以简单的方式实现对象排序或自定义排序. 一.Com ...
- LBS数据分析:使用地图展示统计数据——麻点图与麻数图
作为一个LBS的APP,都获得了用户经纬度,也都使用了友盟统计.google ana等等统计分析系统,不过没有地图展示功能,不能进行直观的展示. 友盟统计.google ana等系统是总体数据统计,无 ...
- jQuery Wheel Menu:实现漂亮的 Path 风格旋转菜单
相信很多用过 Path 的都对它的独特的旋转导航菜单有深刻的印象,这个功能也被很多的 Web 开发者模仿.今天分享的这款插件可以方便的在你的网站中加入和 Path 一样的旋转菜单,可以自定义效果. 您 ...
- 1001Freedownloads – 免费下载海量素材
1001FreeDownloads.com 力求超越所有其他的互联网搜索体验,它拥有超过1000个免费的设计图像和字体的目录.这个独特的网站提供了多种可以用来作为剪贴簿页面,图标和壁纸.不管你需要什么 ...
- iOS UIView设置圆角
UIView设置圆角 1.比较简单的情况,UIView四个角都是圆角: UIView *aView = [[UIView alloc] init]; aView.frame = CGRectMake( ...