程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 讀書筆記-C#中裝箱拆箱性能

讀書筆記-C#中裝箱拆箱性能

編輯:C#入門知識

讀書筆記-C#中裝箱拆箱性能


前言   最近在看王濤大神的《你必須知道的.NET(第二版)》一書,嗯,首先膜拜一下….     在書中的第五章-品味類型中,對裝箱與拆箱一節感觸很深,概念本身相信每一個程序猿都不陌生,裝箱是將值類型轉換為引用類型 ,拆箱是將引用類型轉換為值類型(ps:不小心又背了一下書),也知道裝箱與拆箱過程中將帶來性能上的問題,但是在實際的項目中往往會忽略這個問題,將可能帶來極大的效率上的問題。問題有多大,反正我哭過。   簡單對比測試   在工作之余寫了個簡單的測試例子,以HashTable、ArraryList、List<T>進行了簡單的對比。     運行環境:Windows7_64(Cpu:i5; Ram:6GB)。     代碼如下:   復制代碼 using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics;   namespace Test {     /// <summary>     /// 裝箱拆箱(HashTable ArraryList List<T>)對比     /// </summary>     class Program     {         static void Main(string[] args)         {             while (true)             {                 Console.WriteLine("循環次數:");                 string strcCycleNum = Console.ReadLine();                 int cycleNum = 0;                 if (!int.TryParse(strcCycleNum, out cycleNum))                 {                     Console.WriteLine("無效輸入!");                     continue;                 }                 HashTableCost(cycleNum);                 ArraryListCost(cycleNum);                 GenericCost(cycleNum);             }         }           /// <summary>         /// HashTable 開銷測試         /// </summary>         /// <param name="cycleNum">循環次數</param>         static void HashTableCost(int cycleNum)         {             Stopwatch sw = new Stopwatch();             Hashtable hs_Test = new Hashtable();             sw.Start();             for (int i = 0; i < cycleNum; i++)             {                 hs_Test.Add(i, i);             }             sw.Stop();             ConsoleInfo(cycleNum, "HashTableCost", sw.ElapsedMilliseconds);         }           /// <summary>         /// ArraryList 開銷測試         /// </summary>         /// <param name="cycleNum">循環次數</param>         static void ArraryListCost(int cycleNum)         {             Stopwatch sw = new Stopwatch();             ArrayList al_Test = new ArrayList();             sw.Start();             for (int i = 0; i < cycleNum; i++)             {                 al_Test.Add(i);             }             sw.Stop();             ConsoleInfo(cycleNum, "ArraryListCost", sw.ElapsedMilliseconds);         }           /// <summary>         /// 泛型 開銷測試         /// </summary>         /// <param name="cycleNum">循環次數</param>         static void GenericCost(int cycleNum)         {             Stopwatch sw = new Stopwatch();             List<int> lTest = new List<int>();             sw.Start();             for (int i = 0; i < cycleNum; i++)             {                 lTest.Add(i);             }             sw.Stop();             ConsoleInfo(cycleNum, "GenericCost", sw.ElapsedMilliseconds);         }           /// <summary>         /// 打印信息         /// </summary>         /// <param name="cycleNum">循環次數</param>         /// <param name="methodName">方法名稱</param>         /// <param name="cost">開銷</param>         static void ConsoleInfo(int cycleNum, string methodName, long cost)         {             Console.WriteLine(methodName + " 循環次數:" + cycleNum.ToString() + "  開銷(毫秒):" + cost.ToString());         }       } } 復制代碼 測試結果:   測試結果值   對於測試結果還是很驚訝,循環添加1000次,3者都為0毫秒,在10W與100W次的結果出現了鮮明的對比分別為305ms,86ms,9ms。差距不是一般的大。   對代碼進行分析:   // HashTable : public virtual void Add(object key, object value);  // 在Add的過程中進行了2次裝箱  hs_Test.Add(i, i); HashTable.add()都會產生2次裝箱。   // public virtual int Add(object value); // 產生了一次裝箱  al_Test.Add(i); ArraryList.add產生2次裝箱。   // 由於lTest 指定了類型(List<int>)並沒有產生裝箱 lTest.Add(i); List<int>沒有產生裝箱。   也可以通過IL對代碼進行分析,這裡就不再列出了。   總結 在對大量數據進行操作的時候一定要注意裝箱與拆箱操作,可以用泛型代替的地方還是使用泛型吧。   在平時的一般項目中的細節也需要注意,畢竟細節決定成敗,再NB的框架,也經不起這一片片的裝箱與拆箱的轟炸。   (ps:隱式轉換的時候要細心,在轉換成字符串的時候習慣使用ToString(),畢竟是不產生裝箱的。)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved