一,c#中的值類型和引用類型
眾所周知在c#中有兩種基本類型,它們分別是值類型和引用類型;而每種類型都可以細分為如下類型:
1 class SomRef 2 { 3 public int x; 4 } 5 struct SomeVal { 6 public int x; 7 } 8 class PRogram { 9 static void ValueTypeDemo() {10 SomRef r1 = new SomRef();//在堆上分配11 SomeVal v1 = new SomeVal();//在棧上分配12 r1.x = 5;//提領指針13 v1.x = 5;//在棧上修改14 SomRef r2 = r1;//只復制引用(指針)15 SomeVal v2 = v1;//在棧上分配并復制成員16 }17 }
二,值類型的裝箱和拆箱操作
1 int i = 5;2 object o = i;3 int j = (int)o;
4 Int16 y=(Int16)o;
1 static void Main(string[] args)2 {3 int v = 5;4 object o = v;5 v = 123;6 Console.WriteLine(v+","+(int)o);7 }
通過上面的分析我們已經知道了,裝箱和拆箱/復制操作會對應用程序的速度和內存消耗產生不利的影響(例如消耗內存,增加垃圾回收次數,復制操作),所以我們應該注意編譯器在什么時候會生成代碼來自動這些操作,并嘗試手寫這些代碼,盡量避免自動生成代碼的情況。
你能一眼從上面的代碼中看出進行了幾次裝箱操作嗎?正取答案是3次。分別進行了哪三次呢,我們來看一下:第一次object o=v;第二次在執行 Console.WriteLine(v+","+(int)o);時將v進行裝箱,然后對o進行拆箱后又裝箱。也就是說裝箱過程總是在我們不經意的時候進行的,所以只有我們充分了解了裝箱的內部機制,才能有效的避免裝箱操作,從而提高應用程序的性能。所以對上面的代碼進行如下修改可以減少裝箱次數,從而提高性能:
1 static void Main(string[] args)2 {3 int v = 5;4 object o = v;5 v = 123;6 Console.WriteLine(v.ToString() + "," + ((int)o).ToString());//((int)o).ToString()代碼本身沒有任何意義,只為演示裝箱和拆箱操作7 }
三,泛型的出現(本節只簡單介紹泛型對裝箱和拆箱所起的作用,關于泛型的具體細節請參考下一篇文章)
1 static void Main(string[] args) 2 { 3 ArrayList dateList = new ArrayList { 4 DateTime.Now 5 }; 6 7 IList<DateTime> dateT = new List<DateTime> { 8 DateTime.Now 9 };10 }
使用ArrayList時,每添加一個時間都會進行一次裝箱操作,而使用List<DateTime>時就不會進行裝箱操作,從而提高應用程序的性能。
Queue<T>;
Stack<T>;
List<T>;
Dictionary<Tkey,Tvalue>;
HashSet<T>;
在使用這些集合之前我們必須要理解每一種集合的工作原理(沒事自己可以實現一下),了解每一種集合的適合場合,這樣才能寫出高效的代碼。
四,在設計時如何選擇類和結構體
在面試的時候,我們經常被問的一個問題(還有另外一個問題,如何選擇抽象類和接口,下次我會單獨聊聊這個問題),下面我們來聊聊在設計時應該如何選擇結構體和類
都說程序是一門注重實踐的學科,但是也只有熟悉理解了這些概論的東西,才能在實踐時寫出優秀的代碼,有不對或者不合理的地方歡迎在下面討論;
新聞熱點
疑難解答