C# checked和unchecked详解

1、对基元类型执行的许多算术运算都可能造成溢出,有如下代码:

Byte b=100;
b=(Byte)(b+200);

简单的解读上面的代码:

第一步,将所有的操作数都扩大至32位或者64位(根据操作系统的位数决定)。所以b和200(这两个值都不超过32位),首先转换成32位(假设当前操作系统是32位),然后加到一起。结果就是一个32位值(十进制300或者十六进制12C)。注意此时的值为一个32位的操作数,必须转型为一个byte。C#不会隐式地执行这个转型操作,这正是第二行代码需要强制转换为Byte的原因.如果不把结果值强制转换为Byte,代码如下:

byte b = 100;
b = b +300;

如果将值强行转换为Byte,那么还会出现一个问题,就是值溢出的问题,Byte只能表示0~255范围的值,所以300超出了Byte的范围,值就溢出了.不同的语言以不同的方式处理溢出,C和C++不视溢出为错误,并允许值回滚.应用程序将若无其事的运行.相反,Microsoft Visual Basic总将溢出视为错误,并会在检测到溢出时抛出一个错误.

而CLR提供了一些特殊的IL指令,允许编译器选择它认为最正确的行为。CLR有一个add指令,将作用是将两个值加到一起,但不执行溢出检查。CLR还有一个add.ovf的指令,作用是将两个值加到一起,但会在抛出异常时抛出一个System.OverflowException异常。除了用于加法运算的这两个IL指令外,CLR还为减、乘和数据转换提供了类似的IL指令,分别是sub/sub.ovf,sub/sub.ovf和conv/conv.ovf。

也就是说C#允许程序员自己决定如何处理溢出,溢出检查默认是关闭的。因为这样能保证代码的运行效率,但是开发人员必须保证不会发生溢出,或者他们的代码能预见到这些溢出.

2、控制溢出的方法

第一种:打开/checked编译器开关.这个开关指示编译器在生成代码时,使用加、减、乘、除和转换指令的溢出检查版本也就是带.vof的版本,这样,在生成代码时,就会检查代码是否溢出.

下面是/checked编译器开关的打开方式:

第二种:就是用checked和unchecked关键字来控制溢出的检查与否,这体现的C#溢出检查的灵活性.

下面是一个在/checked编译器开关打开的情况下,使用unchecked关键字强制不检查unchecked包裹的代码的溢出问题,代码如下:

UInt32 a = unchecked((UInt32)(-1));
Console.WriteLine(a); //一个很大的数

下面在/checked编译器开关关闭的情况下,使用checked关键字检查其包裹的代码的溢出问题,代码如下:

byte b = 100;
b =checked((Byte)(b +300)); //溢出错误
Console.WriteLine(b);

3、checked和unchecked语句

除了上面的checked和unchecked关键字外,checked和unchecked还可以是语句,它们造成一个块中的表达式就进行/不进行溢出检查.代码如下:

checked
{
     byte b = 100;
     b += 200;//在checked语句块内,可以直接使用+=操作符,编译器自动会把值转换为byte,前提200必须在byte范围内
     Console.WriteLine(b);
}

4、关于基元类型进行算术操作产生溢出的建议

a、在应用程序能够容忍checked运算造成的性能损失的情况下,尽可能的打开/checked编译器开关,保证程序的正常运行

b、尽量使用有符号整数(Int32,Int64),少使用无符号整数(UInt32,UInt64)

c、将不希望发生overflowException的代码块作用于checked关键字下,并捕获overflowException,并即时从异常中恢复.

d、c的反例,unchecked的用法.

时间: 09-09

C# checked和unchecked详解的相关文章

spring声明式事务配置详解

spring声明式事务配置详解 君子不器 2013年06月16日 编程世界 5273次阅读 查看评论 理解Spring的声明式事务管理实现 本节的目的是消除与使用声明式事务管理有关的神秘性.简单点儿总是好的,这份参考文档只是告诉你给你的类加上@Transactional注解,在配置文件中添加('<tx:annotation-driven/>')行,然后期望你理解整个过程是怎么工作的.此节讲述Spring的声明式事务管理内部的工作机制,以帮助你在面对事务相关的问题时不至于误入迷途,回朔到上游平静

jQuery Validate验证框架详解

jQuery校验官网地址:http://bassistance.de/jquery-plugins/jquery-plugin-validation 一.导入js库 <script type="text/javascript" src="<%=path %>/validate/jquery-1.6.2.min.js"></script> <script type="text/javascript" src

Android进阶——Preference详解之Preference系的基本应用(三)

引言 前面一篇文章Android进阶--Preference详解之Preference系的基本应用和管理(二)介绍了二级Preference的使用和特点,接下来进入系统给我提供的底级Preference的使用CheckBox选择项CheckBoxPreference.EditText编辑对话框EditTextPreference.列表选择ListPreference.多项选择MultiSelectListPreference. 开关选择SwitchPreference的应用和管理.以期大家能在学

【转】jQuery Validate验证框架详解

jQuery校验官网地址:http://bassistance.de/jquery-plugins/jquery-plugin-validation 一.导入js库 <script type="text/javascript" src="<%=path %>/validate/jquery-1.6.2.min.js"></script> <script type="text/javascript" src

[Hive] - Hive参数含义详解

hive中参数分为三类,第一种system环境变量信息,是系统环境变量信息:第二种是env环境变量信息,是当前用户环境变量信息:第三种是hive参数变量信息,是由hive-site.xml文件定义的以及当前hive会话定义的环境变量信息.其中第三种hive参数变量信息中又由hadoop hdfs参数(直接是hadoop的).mapreduce参数.metastore元数据存储参数.metastore连接参数以及hive运行参数构成. Hive-0.13.1-cdh5.3.6参数变量信息详解 参数

CSS3伪类选择器详解

前面花了两节内容分别在<CSS3基本选择器>和<CSS3属性选择器详解>介绍了CSS3选择器中的基本选择器和属性选择器使用方法,今天要和大家一起学习CSS3选择器中的第三部分,也是最后一部分——伪类选择器.伪类选择器对于大家来说最熟悉的莫过于:link,:focus,:hover之类的了,因为这些在平时中是常用到的伪类选择器,那么先和大家一起简单总结一下CSS中常用的伪类选择器的使用方法,最后把重心放到CSS3新增加的":nth-child"选择器的使用方法.

jQuery Validate验证框架详解(转)

jQuery校验官网地址:http://bassistance.de/jquery-plugins/jquery-plugin-validation 一.导入js库 <script type="text/javascript" src="<%=path %>/validate/jquery-1.6.2.min.js"></script> <script type="text/javascript" src

jQuery.validator 详解二

前言:上一篇详细的介绍了jQuery.validator( 版本v1.13.0 )的验证规则,这一篇重点讲述它的源码结构,及如何来对元素进行验证,错误消息提示的内部实现 一.插件结构(组织方式) 在讲述如何对元素进行验证前有必要了解它的代码组织方式,请看代码(部分省略) var plugFn = function( $ ) { $.extend($.fn, { // 验证from表单 validate: function( options ) { // ... // 实例化$.validator

jquery validate 详解二

原文:http://blog.sina.com.cn/s/blog_608475eb0100h3h2.html 这里只是第二篇,前面的内容请参阅上一篇 五.常用方法及注意问题 1.用其他方式替代默认的SUBMIT 1 $().ready(function() { 2 $("#signupForm").validate({ 3 submitHandler:function(form){ 4 alert("submitted"); 5 form.submit(); 6