程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#基礎知識整理 基礎知識 值類型的裝箱和拆箱

C#基礎知識整理 基礎知識 值類型的裝箱和拆箱

編輯:C#入門知識

如果代碼中會造成編譯器的反復裝箱,可改為手動裝箱,這樣來使代碼執行更快,看下面代碼:

[csharp] 
//手動裝箱  
Int32 v = 5; 
 
//由於string.Format的參數是object類型,所以這裡會造成三次裝箱。  
Console.WriteLine(string.Format("{0},{1},{2}", v, v, v)); 
 
//修改一下,當然這只是一個小技巧,比如程序中對同一個值的同一個操作執行多次,  
//應該都是要先執行一次,然後再使用的。  
Object o = v;//裝箱一次  
 
Console.WriteLine(string.Format("{0},{1},{2}", o, o, o)); 

            //手動裝箱
            Int32 v = 5;

            //由於string.Format的參數是object類型,所以這裡會造成三次裝箱。
            Console.WriteLine(string.Format("{0},{1},{2}", v, v, v));

            //修改一下,當然這只是一個小技巧,比如程序中對同一個值的同一個操作執行多次,
            //應該都是要先執行一次,然後再使用的。
            Object o = v;//裝箱一次

            Console.WriteLine(string.Format("{0},{1},{2}", o, o, o));
通過前面的代碼段,我們再寫程序時就很容易判斷什麼時候值類型要裝箱。無非就是當要獲取一個值類型的引用時,就要裝箱。這裡也很清楚的可以看出值類型與引用類型的區別:
1、值類型不在托管堆中分配空間;而引用類型在實例化後就在堆上分配了類中指定的成員的的空間。
2、值類型沒有堆上的對象的額外成員,即“類型對象指針”、“同步索引”。
未裝箱的值類型沒有同步索引,因此不能使用該類型所在類的方法(比如lock)讓多個線程同步對這個實例的訪問。
雖然未裝箱的值類型沒有類型對象指針,但仍可調用由類型繼承或重寫的虛方法,比如Equals,GetHashCode,ToString。如果值類型重寫了其中任何一個虛方法,那麼CLR可以非虛地調用該方法,因為值類型是隱式密封的,沒有任何類型能夠從它派生。此外,用於調用虛方法的值類型實例不會被裝箱。如果重寫的虛方法要調用方法在基類中的實現,那麼在調用基類的實現時,值類型實例會裝箱。因為這些方法是有System.Object定義的,所以這些方法期望this實參是指向堆上的一個對象的指針。
此外,將值類型的一個未裝箱實例轉型為類型的某個接口是,要求實例進行裝箱。因為接口變量必須包含對堆上的一個對象的引用。看下面代碼:
 

[csharp] 
class Program 
   { 
       static void Main(string[] args) 
       { 
           Point p1 = new Point(10, 10); 
 
           Point p2 = new Point(20, 20); 
 
           //調用ToString不裝箱,這裡ToString是一個虛方法  
           Console.WriteLine(p1.ToString()); 
 
           //GetType是一個非虛方法,p1要裝箱  
           Console.WriteLine(p1.GetType()); 
 
           //這裡調用的是public int CompareTo(Point p)  
           //p2不會裝箱  
           Console.WriteLine(p1.CompareTo(p2)); 
 
           //p1要裝箱,這就是將未裝箱的值類型轉為類型的某個接口時  
           IComparable c = p1; 
 
           Console.WriteLine(c.GetType()); 
 
           //這裡調用的是public Int32 CompareTo(Object o),  
           //而且c本來就是一個引用,因此不裝箱了  
           Console.WriteLine(p1.CompareTo(c)); 
 
           //這裡調用的是c的CompareTo方法,參數是object型的  
           //所以要對p2裝箱  
           Console.WriteLine(c.CompareTo(p2)); 
 
           //對c拆箱,並復制值到p2中  
           p2 = (Point)c; 
 
           Console.WriteLine(p2.ToString()); 
       } 
   } 
    
    internal struct Point : IComparable 
   { 
       private Int32 x; 
 
       private Int32 y; 
 
       public Point(Int32 x, Int32 y) 
       { 
           this.x = x; 
 
           this.y = y; 
       } 
 
       public override string ToString() 
       { 
           return string.Format("{0},{1}", x, y);//這裡裝箱兩次,不知道有沒好辦法。  
       } 
 
       public int CompareTo(Point p) 
       { 
           return Math.Sign(Math.Sqrt(x * x + y * y) - Math.Sqrt(p.x * p.x + p.y * p.y)); 
       } 
 
       public Int32 CompareTo(Object o) 
       { 
           if (GetType() != o.GetType()) 
           { 
               throw new ArgumentException("o is not Point."); 
           } 
 
           return CompareTo((Point)o); 
       } 
   } 

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