一个类型转换而引起的三级事件的一些思考

  前段时间出了个三级事件,查下来竟然是因为一个溢出造成的死循环,在公司出事件还是挺冒险的一件事,除了大boss要扣钱,还要给

高层一个合理的解释,如果在小公司干活,可能就算网站宕了一天估计也没事,如果在大点的公司每秒都是银子的流失,也许造成的损失就算

我们白干一二年也抵不了,所以责任心和代码意识真的很重要。

先来看看问题代码,在这里我做了一点点的修改,代码的意思很简单,就是想获取参数num中二进制1的个数。

 1         static void Run(long num)
 2         {
 3             int i = 1;
 4
 5             long num2 = 0;
 6
 7             List<int> list = new List<int>();
 8
 9             while ((num2 = (long)Math.Pow(2, i - 1)) <= num)
10             {
11                 if ((num & num2) > 0)
12                 {
13                     list.Add(i);
14                 }
15                 i++;
16             }
17         }

如果这是你写的代码,你能一眼看出来问题在哪吗?我们知道long是8个字节,也就是64位二进制,又因为二进制位中最高位是符号位,所以当

是2的63次方时,显示的就是long的minvalue,所以上面的代码当i=64的时候,又因为强转成long,所以最后的结果变成了long的MinValue,如

果再循环下去的话就会在负数的道路上越走越远,然后这个范围溢出并没有被CLR采纳,也就没有给我们抛出OverflowException,悲剧就这样

无情的发生了,问题是发生了,但是否能从这个问题上有一些思考,在基元类型的强转中,真的适合用(long),(int)这种强转模式吗?从这个例子

上我们看到这个(long)模式的强转根本就不会检测溢出,所以以后在强转中最好就不要用这种模式了,因为在.net框架下强转的方式太多了,在

我了解的范围内唯独这种没有溢出检测,可能有些人认为这种转换速度是最快的,但是又有多少人可以信誓旦旦的说我的程序绝对不会有溢出,就

算程序有溢出所造成行为异常我也会负全责的?

为了推崇非(long)强转,下面介绍一下其他的强转方式。

一:为了更好的理解代码,我们先来看看原始不检测的模式。

1             long i = long.MaxValue;
2             int j = (int)i;

在IL中我们可以欣喜的看到这种不检测溢出的强转还有专有的IL指令:conv.i4,他的意思就是:将位于计算堆栈顶部的值转换为 int32。

二:checked

在我们学C#语言的那天起,我们就知道有一个checked,他的唯一作用就是检测溢出。如果有则抛出异常,那我们再看看它和无检测的

方式在IL中有什么不同。

1             long i = long.MaxValue;
2
3             checked
4             {
5                 int j = (int)i;
6             }

好家伙,看似大串的代码在IL中居然也就一个指令,其实也就多了一个ovf,这个我想你也应该清楚,在转换的时候多了一个溢出检测。

如果你从性能上反驳的话,确实这个指令性能一定比无检测的慢,我想做web的应该是慢的可以接受。

三:Convet.ToXXX。

这个就是C#给我们专用封装转换操作的类,这个也是我写这篇博客极力推荐的,既然是我推荐的,那肯定是会有检测溢出的,下面我们来

看看代码和IL。

1             long i = long.MaxValue;
2
3             int j = Convert.ToInt32(i);

在IL上我们看到并没有什么特殊的转换指令,那判断肯定就在Toint32方法里面了,下面的目光转移到它的源代码中去看一看。

从源代码中,我们发现原来代码如此的简洁,尤其是这个if,如果当时用了这个ToIntXXX,也许这个事件就会在测试环境被拦截了,也许某一

天,这个if就是你的最后一根救命稻草。

四:IConvertible接口

在这个接口中封装了很多类型转换的方法,而且所有的基元类型都实现了它,不过没有意思的是竟然又调用了下Convert.ToXXX。。。

1             long i = 1;
2
3             int j = ((IConvertible)i).ToInt32(null);

从上面的IL上可以看到,居然有一个box,也难怪IConvertible是引用类型,怎么可能不box呢?这个接口方法在值类型转换场景下不值得提

倡,不方便不说,还有较大的性能损失。

好了,总结性的话也来了。

① 无检测代码模式: 非常不提倡,总有一天会害死你了。

② checked: 这种虽然有检测,但是写起来麻烦,当然也可以在vs里面自己去设置全局检测。

③ Convert.Toxxx: 这篇就是为了提倡它而写的,所以这个重要性我就不说了,总有一天会救你于水火之中的。

④ IConvertible: 在值类型的场景下,性能最烂而且还不好coding。

时间: 2024-08-08 22:06:54

一个类型转换而引起的三级事件的一些思考的相关文章

Sql Server之旅——终点站 nolock引发的三级事件的一些思考

曾今有件事情让我记忆犹新,那年刚来携程不久,马上就被安排写一个接口,供企鹅公司调用他们员工的差旅信息,然后我就三下五除二的给写好 了,上线之后,大概过了一个月...DBA那边报告数据库出现大量锁超时,并且及时根据sql的来源将email发到了我们部门,指出sql读取时间过长, 并且缺少nolock,影响了大量机票订单入库,然后我就拿着sql去生产环境跑了下,22s...花擦...项目上线时间太久,版本已经不存在了,无法 回滚...原本准备撤下接口...看了下撤下接口跟加上nolock时间相差不多

【转载】W3C下的冒泡和捕获机制。到底是冒泡呢。还是捕获呢。一个DOM元素绑定多个事件时如何执行。

原文  http://blog.csdn.net/u011719449/article/details/23787627 在准备阿里前端面试的时候看到这么一道题. 一个DOM元素绑定两个事件,一个冒泡,一个捕获,则事件会执行多少次,执行顺序如何. 这导致了我对冒泡和捕获又进一步深入的了解.(永远都在发现自己知识匮乏的日子中度过人生真是好抓急啊.) 首先冒泡和捕获是怎么一回事. 简单点说.冒泡就是从下往上,像鱼吐泡,泡泡是从下往上升的,也就是DOM元素被触法事件时(此时的dom元素为目标元素),目

分享一个jquery插件,弥补一下hover事件的小小不足

hover事件有一个缺点:当你的鼠标无意划过一个dom元素(瞬间划过,这个时候用户可能不想触发hover事件),会触发hover事件 应该设置一个时差来控制hover事件的触发 比如jd左边的菜单 你用鼠标瞬间划过他子菜单会弹出然后立即消失, 用户体验非常的不好. 易迅的菜单就没有这个问题 delayHover来解决这个问题 啥也不说了先看调用---------- 调用方式: var duration = 500;// 延迟500毫秒 $('#div1').delayHover(function

一个DOM元素绑定多个事件时,先执行冒泡还是捕获

绑定在被点击元素的事件是按照代码顺序发生,其他元素通过冒泡或者捕获“感知”的事件,按照W3C的标准,先发生捕获事件,后发生冒泡事件.所有事件的顺序是:其他元素捕获阶段事件 -> 本元素代码顺序事件 -> 其他元素冒泡阶段事件 . 一个DOM元素绑定两个事件,一个冒泡,一个捕获,则事件会执行多少次,执行顺序如何. 首先来了解一下冒泡和捕获是怎么回事: 1.冒泡 冒泡是从下向上,DOM元素绑定的事件被触发时,此时该元素为目标元素,目标元素执行后,它的的祖元素绑定的事件会向上顺序执行.如下代码所示,

Eventbus的使用与深入-- 一个好用的开源的事件订阅与发布总线,解放你的handler

Eventbus已经发布了很长时间,经历了市场和技术的的考验,与otto齐名,下面来简单了解一下eventbus的使用方法与深入探究. 简单介绍 EventBus是一个用于简化Andorid.Fragment.Threads.Service之间信息传递的一个发布/订阅事件集. 传统的Android组件之间的通信方式有:Activity之间使用Intent:Service向Activity发送broadcast:Fragment和Activity之间相互持有对方的引用(随后可以调用对方的相关方法进

Ogre: 建立一个简单的框架——响应键盘事件

[转载请保证内容的完整性和正确性] 建立一个简单的框架——响应键盘事件 上一节我们在场景中添加了一个机器人,这一节我们将建立一个FrameListener类(顾名思义,这是一个侦听类),来控制模型进行移动. 创建FrameListener类 FrameListener类主要负责事件的侦听,如帧结束.键盘输入等事件.它继承自ExampleFrameListener类,如果需要的话还可以继承KeyListener(键盘事件).MouseListener(鼠标事件)和JoyStickListener(

一次部署HTTPS的相关事件引发的思考

前言: 上周五快要下班的时候,突然收到通知客户希望了解一下部署HTTPS的流程,这种事情谁听了都会有几分诧异的.因为这件事虽然和工作有一定的相关度,但平时不会走这个方向,实际上也较少接触.此外,客户手下应该不缺人,做运维和开发的肯定比我更懂这个,但情况却和我想的不一样. 正文: 客户有需求,就应该尽量满足!因此,尽管之前对Apache.Tomcat的一些配置不熟,也未有过自己部署HTTPS的经验[当然失败的尝试还是有的],便趁着周末了解了一下相关的东西,在本地搭建了环境.实践表明,当你对一个东西

一个清华学生留学香港后对人生的思考

98年本科毕业,又顺利地被保研,当时的我只是一个憨憨的书呆子,纯洁得如同高中生,在清华这种和尚庙一般的理工学校里呆了四年,女孩似乎是山下的老虎,神秘得让我一见就脸红心跳.未来是什么对于我就是“读完研再说”,反正成绩还行,不读白不读.“天上掉了馅饼”,用我的兄弟的话来说.香港正好回归一周年,教育部要选派一批本科毕业生去香港科技大学读研,以加强两地的教育和科研交流.清华当然要占不少名额,系里的几个牛人去了美国,所以这个饼就掉到了我头上,确实是个不错的饼,不用考G.考托.全额奖学金,连什么手续都是学校

用一个简单的例子来演绎事件委托

本篇博文,Insus.NET想使用一个超简单的例子来演绎事件委托.我们在开发网页时,刚开始时在网页的顶部放一个铵钮(web control),想实现一个功能. 在xxx.aspx.cs: OK,某一天,此网页的内容随时间而增长,出现了滚屏.想在网页的底再放一个铵钮,这个铵钮执行事件跟网页顶部铵钮一的事件一样的. 这样子,不管是点击按哪一个铵钮,所执行的事件是一样的:也许一开始你并没有想到onClick的事件名,直接使用铵钮一的onClick的名称,而是如下面的写法:在xxx.aspx.cs,我们