C# checked和unchecked详解
C# checked和unchecked详解
1、对基元类型执行的许多算术运算都可能造成溢出,有如下代码:
1 2 |
|
简单的解读上面的代码:
第一步,将所有的操作数都扩大至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的用法.
相关文章
- C#使用开源类库解析和生成rtf格式的内容
- c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习
- C# DateTime的11种构造函数 [Abp 源码分析]十五、自动审计记录 .Net 登陆的时候添加验证码 使用Topshelf开发Windows服务、记录日志 日常杂记——C#验证码 c#_生成图片式验证码 C# 利用SharpZipLib生成压缩包 Sql2012如何将远程服务器数据库及表、表结构、表数据导入本地数据库
- c# yield关键字原理详解
- c#之泛型详解
- C# IL DASM 使用-破解c#软件方法
- 【C#】?的7种用法
- C#开发中常用的加密解密方法
- c#中Show和Showdialog的区别分析
- c#中将HTML文件转换成PDF文件
- C#字符串常见操作总结详解
- C#连接sqlServer数据库详解
- C#操作SQL Server通用类
- .NET(C#):使用SmtpClient发送带有图片和附件的电子邮件
- C# 变量的作用域
- C#程序集系列05,让程序集包含多个module
- 《Visual C# 2010入门经典》一1.1 .NET Framework
- c#之反射详解
- C#事件详解
- 基于C#语言利用Microsoft.office.introp.excel操作Excel总结
- 《C#零基础入门之百识百例》(三十二)方法参数 -- 引用&输出参数 -- 两数交换
- 《C#零基础入门之百识百例》(九十九)特性详解 -- 自定义特性
- C# 委托详解汇总
- C# 多线程学习系列二
- C# checked和unchecked详解
- 理解 C# 项目 csproj 文件格式的本质和编译流程
- C# checked和unchecked详解
- C#多线程和异步(二)——Task和async/await详解
- C# Panel 打开 Form 窗口的方法
- C# 监测每个方法的执行次数和占用时间(测试4)