原文:[CLR via C#]5.1 基元类型

  某些数据类在开发中非常常用,以至于许多编译器允许代码已简化的语法来操作它们。例如可以使用以下语法来分配一个整数: 

System.Int32 a = new System.Int32();

  当然,你肯定不愿意使用这种语法,C#允许使用如下所示的语法:   

int a = 0;

  这种语法不仅增强代码的可读性,而且生成的IL代码和是有System.Int32时生成的IL代码是完全一致的。

  编译器直接支持的数据类型称为基元类型(primitive type)。基元类型直接映射到Framework类库(FCL)中存在的类型。比如以下4行代码都是正确的,生成的IL代码也是相同的。
int a = 0;
System.Int32 a =0;
int a = new int();
System.Int32 a = new System.Inte32();

  下表列出了FCL类型在C#中对应的基元类型:

C#基元类型 FCL类型 CLS相容 说明
sbyte System.SByte NO 有符号8位值
byte System.Byte YES 无符号8位值
short System.Int16 YES 有符号16位值
ushort System.UInt16 NO 无符号16位值
int System.Int32 YES 有符号32位值
uint System.UInt32 NO 无符号32位值
long System.Int64 YES 有符号64位值
ulong System.UInt64 NO 无符号64位值
char System.Char YES 16位Unicode字符
float System.Single YES IEEE32位浮点值
double System.Double YES IEEE64位浮点值
bool System.Boolean YES 一个true/false值
decimal System.Decimal YES 一个128位高精度浮点值,常用于不容许舍入误差的金融计算
string System.String YES 一个字符数组
object System.Object YES 所有类型的基类型
dynamic System.Object YES 对于CLR,dynamic和object完全一致。然而,C#编译器允许使用一个简单的语法,让dynamic变量参与动态调度

  可以想象C#编译器自动假定在所有的源代码文件中添加了以下using指令:  

using sbyte = System.Sbyte;
using byte = System.Byte;
using int = System.Int32;
using uint = System.UInt32;
......

  C#语言规范上说:"从风格上上,最好使用关键字,而不是使用完整的系统类型名称"。但本书作者并不同意这种说法,以下是他的一些理由:

  1)很多开发人员困惑于应该使用string还是String。由于C#的string(关键字)是直接映射到System.String(一个FCL类型),所以两者是没有区别的。还有开发人员认为,在32位系统中int是32位整数,在64位系统中就变成64位整数了,事实并不是这样。在C#中,int始终映射到System.Inte32,所有不管什么系统,int都是32位整数,如果都使用Int32就不会产生这种误解。

  2)在C#中,long映射到System.Int64,当在其他编程语言中,long可能映射到的是Int16或Int32。这样在看别的编程语言时容易产生误解。

  3)FCL的许多方法都将类型名称作为方法名的一部分。

 
BinaryReader br =new BinaryReader(...);

        float val = br.ReadSingle();      //正确,当看上去不自然

        Single val = br.ReadSingle();    //正确,看上去一目了然
   
  4)平时只用C#的许多程序员逐渐淡忘了还可以使用其他语言写面向CLR的代码。因此造成了"C#主义"入侵类库代码。
  
  对基元类型执行许多算数运算都可能造成溢出。不同语言处理溢出也是不同的。C和C++不将溢出视为错误,并允许值回滚;应用程序"若无其事"的运行着。相反,Microsoft Visual Basic总是将溢出视为错误,并会抛出异常。
 
  CLR提供了一些特殊的IL指令,允许编译器选择它认为最恰当的行为。CLR有一个add指令,将两值相加但不检查溢出。还有一个add.ovf指令,作用是两值相加,溢出时抛出异常。类似的还有sub/sub.ovf等。
 
  C#允许开发人员自己决定如何处理溢出。溢出检查默认是关闭的。开发人员可以使用C#编译器控制溢出的一个办法是使用/checked+编译器开关。
 
  C#通过提供checked和unchecked操作符来实现局部是否检查发生溢出。
unchecked:
UInt32 invalid = unchecked((UInt32)(-1)); //OK
checked:
Byte b = 100;
b = checked((Byte)(n+200)); //抛出溢出异常

  C#还提供checked和unchecked语句

checked{
Byte b = 100;
b = checked((Byte)(n+200));
}

  在Visaul Studio的"高级生成设置"对话框中可以指定编译器是否检查溢出。

  System.Decimal类型是一个非常特殊的类型。虽然C#将Decimal视为一个基元类型,但CLR则不然,也就是说CLR没有相应的IL指令来决定如何处理Decimal值。Decimal值得处理速度是要慢于其他CLR基元类型的值得处理速度。还有对Decimal来说,checked和uncheked操作符、语句和编译器都是无效的,Decimal溢出时是一定会抛出异常的。

[CLR via C#]5.1 基元类型的更多相关文章

  1. CLR via #C读书笔记三:基元类型、引用类型和值类型

    1.一些开发人员说应用程序在32位操作系统上运行,int代表32位整数:在64位操作系统上运行,int代表64位整数.这个说法是完全错误的.C#的int始终映射到System.Int32,所以不管在什 ...

  2. [Clr via C#读书笔记]Cp5基元类型引用类型值类型

    Cp5基元类型引用类型值类型 基元类型 编译器直接支持的类型,基元类型直接映射到FCL中存在的类型. 作者希望使用FCL类型名称而避免使用关键字.他的理由是为了更加的清晰的知道自己写的类型是哪种.但是 ...

  3. CLR:基元类型、引用类型和值类型

    最新更新请访问: http://denghejun.github.io   前言 今天重新看了下关于CLR基元类型的东西,觉得还是有必要将其记录下来,毕竟这是理解CLR成功 之路上的重要一步,希望你也 ...

  4. 《CLR via C#》读书笔记--基元类型、引用类型和值类型

    编程语言的基元类型 编译器直接支持的数据类型称为基元类型.基元类型直接映射到Framework类库中存在的类型.例如:C#中的int直接映射到System.Int32类型.下表给出了C#基元类型与对应 ...

  5. 《CLR via C#》读书笔记(5)基元类型、引用类型和值类型

    5.1 基元类型 编译器直接支持的数据类型称为基元类型(primitive type). 以下4行到吗生成完全相同的IL int a = 0; //最方便的语法 System.Int32 b = 0; ...

  6. 【CLR Via C#】第5章 基元类型、引用类型、值类型

    第二遍看这本书,决定记录一下加深印象. 1,基元类型 什么事基元类型?基元类型是直接映射到FrameWork类库(FCL)中存在的类型,编译器直接支持的数据类型.比如int直接映射到System.In ...

  7. CLR via C#深解笔记三 - 基元类型、引用类型和值类型 | 类型和成员基础 | 常量和字段

    编程语言的基元类型   某些数据类型如此常用,以至于许多编译器允许代码以简化的语法来操纵它们. System.Int32 a = new System.Int32();  // a = 0 a = 1 ...

  8. [CLR via C#]5.4 对象哈希码和dynamic基元类型

    原文:[CLR via C#]5.4 对象哈希码和dynamic基元类型 FCL的设计者认为,如果能将任何对象的任何实例放到一个哈希表集合中,会带来很多好处.为此,System.Object提供了虚方 ...

  9. <NET CLR via c# 第4版>笔记 第5章 基元类型、引用类型和值类型

    5.1 编程语言的基元类型 c#不管在什么操作系统上运行,int始终映射到System.Int32; long始终映射到System.Int64 可以通过checked/unchecked操作符/语句 ...

随机推荐

  1. CacheManager

    .Net缓存管理框架CacheManager Cache缓存在计算机领域是一个被普遍使用的概念.硬件中CPU有一级缓存,二级缓存, 浏览器中有缓存,软件开发中也有分布式缓存memcache, redi ...

  2. sql 添加用户

    use master GO EXEC sp_addlogin 'infos1', '1', 'master' exec sp_grantdbaccess 'infos311' -- 给访问权限 USE ...

  3. iOS8发展~Swift(三)UI详细解释

    一个.总结 使用Swift去完成iOS的UI接口,事实上,目前的想法和OC实现几乎一致,只是在措辞非常大的差异,修改前更更大的个人控制.为有纯代码强迫症,所以接下来创建一个纯代码动项目,然后在此基础上 ...

  4. StackExchange.Redis Client

    StackExchange.Redis Client 这期我们来看StackExchange.Redis,这是redis 的.net客户端之一.Redis是一个开源的内存数据存储,可以用来做数据库,缓 ...

  5. 孙陪你,了解它的权力--Kinect结合的发展Unity3D游戏应用开发

    unity3d正在使用kinect三维模型数据控制(它切成脚本) 博主在做项目时须要利用kinect数据控制三维模型中人物的动作.但不是实时控制,而是利用之前获得的骨骼数据,直接控制.无需再利用脚本打 ...

  6. target-action传值

    Target-Action传值 实质就是:A页面要给B页面传值,A就提供接口出去,抓A到B内部来,A间接调用自己内部方法(相当于,A把自己内部需                     要操作的方法, ...

  7. 不一样的是不一样的,我的独家滚动条------Day35

    在您开始建立自己的,感觉应该先录一个概念:内核的浏览器. 兼容性问题之前多次提及,而在平时经常会遇到兼容性问题.原因,就在于它:浏览器内核.这是比較通俗的说法,事实上应该把它描写叙述的专业点:Rend ...

  8. JavaScript运行命令

    前言 动人js一段时间,我认为事情仅仅是一个很肤浅的理解.是非常欠缺的.所以開始使用博客来对这一部分的知识做个慢慢的记录和积累. 相信积少成多,慢慢的将这一部分的知识攻克! 第一篇记录的不是相关的应用 ...

  9. iOS一个开发系列中 - UIButton 使用摘要

    // 初始化button并设置类型 UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; // 可以定义的UIButto ...

  10. JAVA —— 数据类型

    引言:java 数据类型可分为两大类:基本数据类型和引用类型,其中基本数据类型又包括整形.浮点型.字符型和布尔型,而引用型变量与基本类型变量不同,它的值是指向内存空间的引用(地址),引用在其他语言中称 ...