国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

一個類型轉換而引起的三級事件的一些思考

2019-11-14 16:25:14
字體:
來源:轉載
供稿:網友

 

  前段時間出了個三級事件,查下來竟然是因為一個溢出造成的死循環,在公司出事件還是挺冒險的一件事,除了大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             checked4             {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。

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 五河县| 南京市| 平阴县| 海伦市| 汉中市| 鹤山市| 无棣县| 定远县| 武功县| 上蔡县| 楚雄市| 宜兰县| 三门县| 珠海市| 桐柏县| 古丈县| 潮安县| 弋阳县| 安达市| 卓尼县| 宜都市| 肇州县| 都匀市| 龙南县| 塔城市| 萝北县| 伊通| 玉山县| 杨浦区| 桃江县| 精河县| 西昌市| 观塘区| 浦江县| 乐清市| 红桥区| 淳安县| 乐昌市| 应城市| 瓦房店市| 凯里市|