仔細了解裝箱和拆箱其實是很有趣的,首先來看為什麼會裝箱和拆箱呢?
看下面一段程式碼:
class Program { static void Main(string[] args) { ArrayList array = new ArrayList(); Point p;//分配一个 for (int i = 0; i < 5; i++) { p.x = i;//初始化值 p.y = i; array.Add(p);//装箱 } } } public struct Point { public Int32 x; public Int32 y; }
循環5次,每次都初始化一個Point值類型字段,然後放到ArrayList。 Struct是一個值類型的結構,那麼ArrayList中存的什麼呢?我們再看一下ArrayList的Add方法。 MSDN中可以看到Add方法:
public virtual int Add(Object value),
可以看出Add的參數是Object類型,也就是它所需要的參數是一個物件的參考。也就是說這裡的參數必須是引用型別。至於何為引用類型,就不必細說了,無非就是堆上的一個物件的引用。不過在這裡為了方便理解,再次說一下堆疊和堆疊。
1、堆疊區(stack)— 由編譯器自動指派釋放 ,存放函數的參數值,局部變數的值等。
2、堆疊區(heap)— 由程式設計師指派釋放, 若程式設計師不釋放,程式結束時可能由OS回收。
例如下面:
class Program { static void Main(string[] args) { Int32 n;//这是值类型,存放在栈中,Int32初始值为0 A a;//此时在栈中开辟了空间 a = new A();//真正实例化后的一个对象则保存在堆中。 } } public class A { public A() { } }
再回到上面的問題中,Add方法需要引用類型的參數,怎麼辦呢?那就要用到裝箱,所謂裝箱,就是將一個值型別轉換為一個引用型別。轉換的過程是這樣的:
1、在託管堆中分配好記憶體。分配的記憶體量是值類型的各個欄位所需的記憶體量加上託管堆的所有物件都有的兩個額外成員(類型物件指標和同步區塊索引)所需的記憶體量。
2、值類型的欄位複製到新分配的對記憶體。
3、回傳對象的位址。此時,這個位址是對一個物件的引用,值類型現在已經轉換為了一個引用型別。
這樣,在Add方法中,保存的是一個被裝箱的Point物件的引用。裝箱後的這個物件會一直在堆中,知道程式設計師處理或系統垃圾回收。這時,已裝箱的值類型的生存週期超過了未裝箱的值類型的生存週期。
有了上面的裝箱,自然就需要拆箱了,如果要取出array的第0個:
Point p = (Point)array[0];
這裡要做的是,獲取ArrayList的元素0的引用,將其放到Point值類型p中。為了達到這個目的,如何實現呢,首先,取得已裝箱的Point物件的各個Point欄位的位址。這就是拆箱。然後,將這些欄位包含的值從堆疊中複製到基於堆疊的值類型實例中。拆箱其實就是取得一個引用的過程,該引用指向包含在一個物件中的原始值類型。事實上,引用指向的是已裝箱實例中的未裝箱部分。因此和裝箱不同,拆箱不需要在記憶體中複製任何位元組。不過還有一點,拆箱後緊接著發生一次欄位的複製操作。
所以裝箱和拆箱會對程式的速度和記憶體消耗造成不利影響,所以要注意什麼時候程式會自動進行裝箱/拆箱操作,在寫程式碼時要盡量避免這些情況。
拆箱時,請注意下面的例外:
1、如果包含了「已裝箱值類型實例的參考」的變數為null,會拋出NullReferenceException。
2、如果引用指向的物件不是所期望的值類型的已裝箱實例,會拋出InvalidCastException。
例如以下程式碼片段:
Int32 x = 5; Object o = x; Int16 r = (Int16)o;//抛出InvalidCastException异常
因為拆箱時候只能將其轉換為原來未裝箱時的值類型。上述程式碼修改為:
Int32 x = 5; Object o = x; //Int16 r = (Int16)o;//抛出InvalidCastException异常 Int16 r = (Int16)(Int32)o;
此時正確。
在拆箱後,會發生一次字段複製,如下代碼:
//会发生字段复制 Point p1; p1.x = 1; p1.y = 2; Object o = p1;//装箱,发生复制 p1 = (Point)o;//拆箱,并将字段从已装箱的实例复制到栈中
再看如下代碼段:
//要改变已装箱的值 Point p2; p2.x = 10; p2.y = 20; Object o = p2;//装箱 p2 = (Point)o;//拆箱 p2.x = 40;//改变栈中变量的值 o = p2;//再一次装箱,o引用新的已装箱实例
這裡的目的是要將裝箱後的p2的x值改為40,這樣,就需要先拆一次箱,執行一次複製欄位到堆疊中,在堆疊中改變欄位的值,然後執行一次裝箱,這時又要在堆上建立一個全新的已裝箱實例。由此也我們也看到裝箱/拆箱和複製對程式效能的影響。
下面再看幾個裝箱拆箱的程式碼段:
//装箱拆箱演示 Int32 v = 5; Object o = v; v = 123; Console.WriteLine(v + "," + (Int32)o);
這裡發生了3次裝箱,可明顯看出的是
Object o = v; v = 123;
但是在Console.WriteLine裡還發生了一次裝箱,為什麼呢?因為這裡的WriteLine中是string型別的參數,而string大家都知道是引用型的,所以(Int32)o在這裡還要進行一次裝箱。這裡再次說明了在程式中使用+號連接字串的問題,連接的時候有幾個值類型,那麼就要進行幾次裝箱操作。
不過,上述程式碼可以修改:
//修改后 Console.WriteLine(v.ToString() + "," + o);
這樣就沒有裝箱了。
再看如下程式碼:
Int32 v = 5; Object o = v; v = 123; Console.WriteLine(v); v = (Int32)o; Console.WriteLine(v);
這裡只發生了一次裝箱,即Object o = v這裡,而Console.WriteLine由於重載了int,bool,double等,所以這裡並不發生裝箱。
以上就是C#基礎知識整理 基礎知識(18) 值類型的裝箱與拆箱(一)的內容,更多相關內容請關注PHP中文網(www.php.cn)!

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

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

.NETFramework是一個軟件框架,C#是一種編程語言。 1..NETFramework提供庫和服務,支持桌面、Web和移動應用開發。 2.C#設計用於.NETFramework,支持現代編程功能。 3..NETFramework通過CLR管理代碼執行,C#代碼編譯成IL後由CLR運行。 4.使用.NETFramework可快速開發應用,C#提供如LINQ的高級功能。 5.常見錯誤包括類型轉換和異步編程死鎖,調試需用VisualStudio工具。

C#是一種由微軟開發的現代、面向對象的編程語言,.NET是微軟提供的開發框架。 C#結合了C 的性能和Java的簡潔性,適用於構建各種應用程序。 .NET框架支持多種語言,提供垃圾回收機制,簡化內存管理。

C#和.NET運行時緊密合作,賦予開發者高效、強大且跨平台的開發能力。 1)C#是一種類型安全且面向對象的編程語言,旨在與.NET框架無縫集成。 2).NET運行時管理C#代碼的執行,提供垃圾回收、類型安全等服務,確保高效和跨平台運行。

要開始C#.NET開發,你需要:1.了解C#的基礎知識和.NET框架的核心概念;2.掌握變量、數據類型、控制結構、函數和類的基本概念;3.學習C#的高級特性,如LINQ和異步編程;4.熟悉常見錯誤的調試技巧和性能優化方法。通過這些步驟,你可以逐步深入C#.NET的世界,並編寫高效的應用程序。

C#和.NET的關係是密不可分的,但它們不是一回事。 C#是一門編程語言,而.NET是一個開發平台。 C#用於編寫代碼,編譯成.NET的中間語言(IL),由.NET運行時(CLR)執行。

C#.NET依然重要,因為它提供了強大的工具和庫,支持多種應用開發。 1)C#結合.NET框架,使開發高效便捷。 2)C#的類型安全和垃圾回收機制增強了其優勢。 3).NET提供跨平台運行環境和豐富的API,提升了開發靈活性。


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

WebStorm Mac版
好用的JavaScript開發工具