搜尋
首頁後端開發C#.Net教程c#裝箱與拆箱知識整理

1、裝箱和拆箱是一個抽象的概念 
2、裝箱是將值型別轉換為引用型別;

拆箱是將引用型別轉換為值型別

利用裝箱和拆箱功能,可透過允許值類型的任何值與Object 類型的值相互轉換,將值類型與引用類型連結起來

例如:

int val = 100; 
object obj = val; 
Console.WriteLine (“对象的值 = {0}", obj);

這是一個裝箱的過程,是將值類型轉換為引用類型的過程 

int val = 100; 
object obj = val; 
int num = (int) obj; 
Console.WriteLine ("num: {0}", num);

這是一個拆箱的過程,是將值型別轉換為參考型,再由參考型別轉換為值型別的過程

註:被裝過箱的物件才能被拆箱
3、.NET中,數據類型劃分為值類型和引用(不等同於C++的指標)類型,與此對應,記憶體分配被分成了兩種方式,一為棧,二為堆(注意:是託管堆)
值類型只會在棧中分配。
引用型別分配記憶體與託管堆。
託管堆對應於垃圾回收。

4:裝箱/拆箱是什麼? 
裝箱:用於在垃圾回收堆中儲存值類型。裝箱是值類型到 object 類型或到此值類型所實現的任何介面類型的隱式轉換。 
拆箱:從 object 類型到值類型或從介面類型到實現該介面的值類型的明確轉換。

5:為何需要裝箱? (為何要將值型別轉換為參考型別?) 
最普通的場景是,呼叫一個含型別為Object的參數的方法,該Object可支援任意為型,以便通用。當你需要將一個值類型(如Int32)傳入時,就需要裝箱。 
另一種用法是,一個非泛型的容器,同樣是為了保證通用,而將元素類型定義為Object。於是,要將值類型資料加入容器時,需要裝箱。

6:裝箱/拆箱的內部操作

裝箱
對值類型在堆中分配一個物件實例,並將該值複製到新的物件中。按三步驟進行。

新分配託管堆記憶體(大小為值類型實例大小加上一個方法表指標和一個SyncBlockIndex)。 
將值類型的實例欄位拷貝到新分配的記憶體中。 
傳回託管堆中新分配物件的位址。這個位址就是一個指向物件的引用了。 
有人這樣理解:如果將Int32裝箱,回傳的位址,指向的就是一個Int32。我認為也不是不能這樣理解,但這確實又有問題,一來它不全面,二來指向Int32並沒說出它的實質(在託管堆中)。

拆箱
檢查物件實例,確保它是給定值類型的一個裝箱值。將該值從實例複製到值類型變數中。 
有書上講,拆箱只是取得引用物件中指向值類型部分的指針,而內容拷貝則是賦值語句之觸發。我覺得這並不要緊。最關鍵的是檢查物件實例的本質,拆箱和裝箱的類型必需匹配,這一點上,在IL層上,看不出原理何在,我的猜測,或許是調用了類似GetType之類的方法來取出類型進行配對(因為需要嚴格配對)。

7:裝箱/拆箱對執行效率的影響

顯然,從原理上可以看出,裝箱時,生成的是全新的引用對象,這會有時間損耗,也就是造成效率降低。 
那該如何做呢? 
首先,應盡量避免裝箱。 
例如上例2的兩種情況,都可以避免,在第一種情況下,可以透過重載函數來避免。第二種情況,則可以透過泛型來避免。 
當然,凡事並不能絕對,假設你想改造的程式碼為第三方程式集,你無法更改,那你只能是裝箱了。
對於裝箱/拆箱程式碼的最佳化,由於C#中對裝箱和拆箱都是隱式的,所以,根本的方法是對程式碼進行分析,而分析最直接的方式是了解原理結何查看反編譯的IL程式碼。

例如:在循環體中可能存在多餘的裝箱,你可以簡單採用提前裝箱方式進行最佳化。

8:對裝箱/拆箱更進一步的了解

裝箱/拆箱並不如上面所講那麼簡單明了

比如:裝箱時,變為引用對象,會多出一個方法表指針,這會有何用處呢?

我們可以透過範例來進一步探討。

舉例:

Struct A : ICloneable
{
public Int32 x;
public override String ToString() {
return String.Format(”{0}”,x);
}
public object Clone() {
return MemberwiseClone();
}
}
static void main() 
{ 
A a; 
a.x = 100; 
Console.WriteLine(a.ToString()); 
Console.WriteLine(a.GetType()); 
A a2 = (A)a.Clone(); 
ICloneable c = a2; 
Ojbect o = c.Clone(); 
}

a.ToString()。编译器发现A重写了ToString方法,会直接调用ToString的指令。因为A是值类型,编译器不会出现多态行为。因此,直接调用,不装箱。(注:ToString是A的基类System.ValueType的方法) 
a.GetType(),GetType是继承于System.ValueType的方法,要调用它,需要一个方法表指针,于是a将被装箱,从而生成方法表指针,调用基类的System.ValueType。(补一句,所有的值类型都是继承于System.ValueType的)。 
a.Clone(),因为A实现了Clone方法,所以无需装箱。 
ICloneable转型:当a2为转为接口类型时,必须装箱,因为接口是一种引用类型。 
c.Clone()。无需装箱,在托管堆中对上一步已装箱的对象进行调用。 
附:其实上面的基于一个根本的原理,因为未装箱的值类型没有方法表指针,所以,不能通过值类型来调用其上继承的虚方法。另外,接口类型是一个引用类型。对此,我的理解,该方法表指针类似C++的虚函数表指针,它是用来实现引用对象的多态机制的重要依据。

9:如何更改已装箱的对象

对于已装箱的对象,因为无法直接调用其指定方法,所以必须先拆箱,再调用方法,但再次拆箱,会生成新的栈实例,而无法修改装箱对象。有点晕吧,感觉在说绕口令。还是举个例子来说:(在上例中追加change方法) 

public void Change(Int32 x) { 
this.x = x; 
}

调用: 

A a = new A(); 
a.x = 100; 
Object o = a; //装箱成o,下面,想改变o的值
((A)o).Change(200); //改掉了吗?没改掉
没改掉的原因是o在拆箱时,生成的是临时的栈实例A,所以,改动是基于临时A的,并未改到装箱对象。

(附:在托管C++中,允许直接取加拆箱时第一步得到的实例引用,而直接更改,但C#不行。) 
那该如何是好? 
嗯,通过接口方式,可以达到相同的效果。 
实现如下: 

interface IChange { 
void Change(Int32 x); 
} 
struct A : IChange { 
… 
}

调用: 

((IChange)o).Change(200);//改掉了吗?改掉了

为啥现在可以改?


在将o转型为IChange时,这里不会进行再次装箱,当然更不会拆箱,因为o已经是引用类型,再因为它是IChange类型,所以可以直接调用Change,于是,更改的也就是已装箱对象中的字段了,达到期望的效果。

10、将值类型转换为引用类型,需要进行装箱操作(boxing):

首先从托管堆中为新生成的引用对象分配内存
然后将值类型的数据拷贝到刚刚分配的内存中
返回托管堆中新分配对象的地址
可以看出,进行一次装箱要进行分配内存和拷贝数据这两项比较影响性能的操作。

将引用类型转换为值类型,需要进行拆箱操作(unboxing):

首先获取托管堆中属于值类型那部分字段的地址,这一步是严格意义上的拆箱。
将引用对象中的值拷贝到位于线程堆栈上的值类型实例中。
经过这2步,可以认为是同boxing是互反操作。严格意义上的拆箱,并不影响性能,但伴随这之后的拷贝数据的操作就会同boxing操作中一样影响性能。

11、

NET的所有类型都是由基类System.Object继承过来的,包括最常用的基础类型:int, byte, short,bool等等,就是说所有的事物都是对象。

如果申明这些类型得时候都在堆(HEAP)中分配内存,会造成极低的效率!(个中原因以及关于堆和栈得区别会在另一篇里单独得说说!)
.NET如何解决这个问题得了?正是通过将类型分成值型(value)和引用型(regerencetype),

C#中定义的值类型和引用类型

值类型:原类型(Sbyte、Byte、Short、Ushort、Int、Uint、Long、Ulong、Char、Float、Double、Bool、Decimal)、枚举(enum)、结构(struct)
引用类型:类、数组、接口、委托、字符串等
值型就是在栈中分配内存,在申明的同时就初始化,以确保数据不为NULL;
引用型是在堆中分配内存,初始化为null,引用型是需要GARBAGE COLLECTION来回收内存的,值型不用,超出了作用范围,系统就会自动释放!
下面就来说装箱和拆箱的定义!
装箱就是隐式的将一个值型转换为引用型对象。比如:

int i=0;
Syste.Object obj=i;

这个过程就是装箱!就是将i装箱!
拆箱就是将一个引用型对象转换成任意值型!比如:

int i=0;
System.Object obj=i;
int j=(int)obj;

这个过程前2句是将i装箱,后一句是将obj拆箱!

更多c#装箱和拆箱知识整理相关文章请关注PHP中文网!


陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
C#.NET的未來:趨勢和機遇C#.NET的未來:趨勢和機遇Apr 29, 2025 am 12:02 AM

C#.NET的未來趨勢主要集中在雲計算、微服務、AI和機器學習集成以及跨平台開發三個方面。 1)雲計算和微服務:C#.NET通過Azure平台優化雲環境表現,支持構建高效微服務架構。 2)AI和機器學習集成:借助ML.NET庫,C#開發者可在應用中嵌入機器學習模型,推動智能化應用發展。 3)跨平台開發:通過.NETCore和.NET5 ,C#應用可在Windows、Linux和macOS上運行,擴展部署範圍。

C#.NET開發今天:趨勢和最佳實踐C#.NET開發今天:趨勢和最佳實踐Apr 28, 2025 am 12:25 AM

C#.NET開發的最新動態和最佳實踐包括:1.異步編程提高應用響應性,使用async和await關鍵字簡化非阻塞代碼;2.LINQ提供強大查詢功能,通過延遲執行和表達式樹高效操作數據;3.性能優化建議包括使用異步編程、優化LINQ查詢、合理管理內存、提升代碼可讀性和維護性、以及編寫單元測試。

C#.NET:使用.NET生態系統構建應用程序C#.NET:使用.NET生態系統構建應用程序Apr 27, 2025 am 12:12 AM

如何利用.NET構建應用?使用.NET構建應用可以通過以下步驟實現:1)了解.NET基礎知識,包括C#語言和跨平台開發支持;2)學習核心概念,如.NET生態系統的組件和工作原理;3)掌握基本和高級用法,從簡單控制台應用到復雜的WebAPI和數據庫操作;4)熟悉常見錯誤與調試技巧,如配置和數據庫連接問題;5)應用性能優化與最佳實踐,如異步編程和緩存。

C#作為多功能.NET語言:應用程序和示例C#作為多功能.NET語言:應用程序和示例Apr 26, 2025 am 12:26 AM

C#在企業級應用、遊戲開發、移動應用和Web開發中均有廣泛應用。 1)在企業級應用中,C#常用於ASP.NETCore開發WebAPI。 2)在遊戲開發中,C#與Unity引擎結合,實現角色控制等功能。 3)C#支持多態性和異步編程,提高代碼靈活性和應用性能。

C#.NET用於網絡,桌面和移動開發C#.NET用於網絡,桌面和移動開發Apr 25, 2025 am 12:01 AM

C#和.NET適用於Web、桌面和移動開發。 1)在Web開發中,ASP.NETCore支持跨平台開發。 2)桌面開發使用WPF和WinForms,適用於不同需求。 3)移動開發通過Xamarin實現跨平台應用。

C#.NET生態系統:框架,庫和工具C#.NET生態系統:框架,庫和工具Apr 24, 2025 am 12:02 AM

C#.NET生態系統提供了豐富的框架和庫,幫助開發者高效構建應用。 1.ASP.NETCore用於構建高性能Web應用,2.EntityFrameworkCore用於數據庫操作。通過理解這些工具的使用和最佳實踐,開發者可以提高應用的質量和性能。

將C#.NET應用程序部署到Azure/AWS:逐步指南將C#.NET應用程序部署到Azure/AWS:逐步指南Apr 23, 2025 am 12:06 AM

如何將C#.NET應用部署到Azure或AWS?答案是使用AzureAppService和AWSElasticBeanstalk。 1.在Azure上,使用AzureAppService和AzurePipelines自動化部署。 2.在AWS上,使用AmazonElasticBeanstalk和AWSLambda實現部署和無服務器計算。

C#.NET:強大的編程語言簡介C#.NET:強大的編程語言簡介Apr 22, 2025 am 12:04 AM

C#和.NET的結合為開發者提供了強大的編程環境。 1)C#支持多態性和異步編程,2).NET提供跨平台能力和並發處理機制,這使得它們在桌面、Web和移動應用開發中廣泛應用。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境