詳解 C# 中的裝箱與拆箱


在C#中,裝箱(boxing)是把值類型轉換為System.Object類型,或者轉換為由值類型實現的接口類型。拆箱(unboxing)是相反的轉換過程。
例如,以下結構類型:

  struct MyStruct
  {
    public int Val;
  }

注:struct 結構體是值類型。
可以把這種類型的結構放在object類型的變量中,對其裝箱:

  MyStruct valType1 = new MyStruct();
  valType1.Val = 1;
  object refType = valType1;

其中創建了一個類型為MyStruct的新變量valType1,並把一個值"1"賦予這個結構的Val成員,然后把它裝箱在object類型的變量refType中。
以這種方式裝箱變量而創建的對象,會包含值類型變量的一個副本的引用,而不包含源值類型變量的引用。要進行驗證,可以修改源結構的內容,把對象中包含的結構拆箱到新變量中,檢查其內容:

  valType1.Val = 2;
  MyStruct valType2 = (MyStruct)refType;
  WriteLine($"valType2.Val = {valType2.Val}");

執行這段代碼將得到如下輸出結果:
  valType2.Val = 1
但在把一個引用類型賦予對象時,將執行不同的操作。把MyStruct改為一個類(不考慮這個類名不合適的情況),即可看到這種情形:

  class
MyStruct
  {
    public int Val;
  }

如果不修改上面的客戶代碼(再次忽略名稱有誤的變量),就會得到如下輸出結果:
  valType2.Val = 2
也可以把值類型裝箱到接口類型中,只要它們實現這個接口即可。例如,假定MyStruct類型實現IMyInterface接口,如下所示:

  interface IMyInterface {}
  struct MyStruct : IMyInterface
  {
    public int Val;
  }

接着把結構裝箱到一個IMyInterface類型中,如下所示:

  MyStruct valType1 = new MyStruct();
  IMyInterface refType = valType1;

然后使用一般的數據類型轉換語法對其拆箱:
  MyStruct ValType2 = (MyStruct)refType;
從這些示例中可以看出,裝箱是在沒有用戶干涉的情況下進行的(即不需要編寫任何代碼),但拆箱一個值需要進行顯式轉換,即需要進行數據類型轉換(裝箱是隱式的,所以不需要進行數據類型轉換)。
您可能想知道為什么要這么做。裝箱非常有用,有兩個非常重要的原因。首先,它允許在項的類型是object的集合(如ArrayList)中使用值類型。其次,有一個內部機制允許在值類型(例如int和結構)上調用object方法。
最后需要注意的是,在訪問值類型內容前,必須進行拆箱。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM