加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 04:40:52 所属栏目:百科 来源:网络整理
导读:前段时间出了个三级事件,查下来竟然是因为一个溢出造成的死循环,在公司出事件还是挺冒险的一件事,除了大boss要扣钱,还要给 高层一个合理的解释,如果在小公司干活,可能就算网站宕了一天估计也没事,如果在大点的公司每秒都是银子的流失,也许造成的损失

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

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

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

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

Run( i = num2 = List<> list = List<> ((num2 = ()Math.Pow(,i - )) <= ((num & num2) > 0 i++ }

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

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

i = j = ()i;

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

二:checked

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

方式在IL中有什么不同。

i = j = ( }

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

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

三:Convet.ToXXX。

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

看看代码和IL。

i = j = Convert.ToInt32(i);

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

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

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

四:IConvertible接口

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

i = j = ((IConvertible)i).ToInt32();

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

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

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

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

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

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读