《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操作符/语句 ...
随机推荐
- EC笔记,第一部分:3.尽量使用const
03.尽量使用const 1.const概述 2.返回const 为何要返回一个const? 因为如果不返回const,程序员可能写出fun(a,b)=c;这样的代码,也许是因为打字错误可能写出类似i ...
- Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
场景:eclipse中编写java中用到数组 问题: 程序不报错但是运行过程中 终止,显示字样 “ Exception in thread "main" java.lang.Arr ...
- PHP与MySQL的交互(mysqli)
近期在学习PHP,这里总结一下PHP与MySQL的交互. 这里我们使用mysqli进行连接. mysqli扩展允许我们访问MySQL 4.1及以上版本提供的功能. 想深入了解mysqli的信息可以访问 ...
- [javaSE] 反射-方法的反射
1.如何获取某个方法 方法的名称和方法的参数列表才能唯一决定一个方法 2.方法反射的操作 method.invoke(); package com.tsh.reflect; import java.l ...
- Linux命令速查手册,超详细Linux命令教程
一.常用命令速查 ls cd pwd cat more less tail head cp scp mv mkdir rmdir touch rm ps kill top free clear tre ...
- windows不能显示此连接属性。windows management instrumentation (WMI) 信息可能损坏
Windows Management Instrumentation (WMI)信息可能损坏错误修复 在 查看“本地连接”的属性,并切换到“高级”选项卡后,提示:“Windows不能显示此连接的属性. ...
- windows根据端口号找进程
d:\>netstat -ano | findstr "7777" TCP 127.0.0.1:7776 127.0.0.1:7777 ESTABLISHED 11764 T ...
- 博客迁移到独立域名owenchen.net,此博客不再更新。
博客已迁移到阿里云,自己搭的wordpress,可以有更多的灵活性. 写点代码,放点示例,欢迎访问. owenchen.net
- go语言 新手学习笔记 go基础教程
目前这方面的资料相对较少,自己手动整理汇集. 第一章:安装 第一节:下载go语言 第二节:windows 安装 go语言 第三节: 第二章:基本语法 第一节:类型 .
- DOM事件类型详解
一.表单事件: input事件当<input>.<textarea>的值发生变化时触发.此外,打开contenteditable属性的元素,只要值发生变化,也会触发input事 ...