ASP.NET堆和棧三之引用類型對(duì)象拷貝和內(nèi)存分配
".NET的堆和棧"系列:
在" ASP.NET堆和棧一之基本概念和值類型內(nèi)存分配"中,了解了"堆"和"棧"的基本概念,以及值類型的內(nèi)存分配。我們知道:當(dāng)執(zhí)行一個(gè)方法的時(shí)候,值類型實(shí)例會(huì)在"棧"上分配內(nèi)存,而引用類型實(shí)例會(huì)在"堆"上分配內(nèi)存,當(dāng)方法執(zhí)行完畢,"棧"上的實(shí)例由操作系統(tǒng)自動(dòng)釋放,"堆"上的實(shí)例由.NET Framework的GC進(jìn)行回收。
在" ASP.NET堆和棧二之值類型和引用類型參數(shù)傳遞和內(nèi)存分配"中,我們了解了值類型參數(shù)和引用類型參數(shù)在傳遞時(shí)的內(nèi)存分配情況。
而本篇的重點(diǎn)要放在:引用類型對(duì)象拷貝以及內(nèi)存分配。
引用類型對(duì)象拷貝 成員都是值類型
public struct Shoe{ public string Color;} public class Dude{ public string Name; public Shoe RightShoe; public Shoe LeftShoe; public Dude CopyDude() {Dude newPerson = new Dude();newPerson.Name = Name;newPerson.LeftShoe = LeftShoe;newPerson.RightShoe = RightShoe; return newPerson; } public override string ToString() {return (Name + " : Dude!, I have a " + RightShoe.Color +" shoe on my right foot, and a " +LeftShoe.Color + " on my left foot."); } }public static void Main(){ Dude Bill = new Dude(); Bill.Name = "Bill"; Bill.LeftShoe = new Shoe(); Bill.RightShoe = new Shoe(); Bill.LeftShoe.Color = Bill.RightShoe.Color = "Blue"; Dude Ted = Bill.CopyDude(); Ted.Name = "Ted"; Ted.LeftShoe.Color = Ted.RightShoe.Color = "Red"; Console.WriteLine(Bill.ToString()); Console.WriteLine(Ted.ToString()); }
輸出結(jié)果:
Bill : Dude!, I have a Red shoe on my right foot, and a Red on my left foot
Ted : Dude!, I have a Red shoe on my right foot, and a Red on my left foot
以上,當(dāng)引用類型的屬性、成員都是值類型的時(shí)候,拷貝是完全拷貝。
引用類型對(duì)象拷貝 包含引用類型成員
把Shoe由struct值類型改成引用類型class。
public class Shoe{ public string Color;}
再次運(yùn)行,輸出結(jié)果:
Bill : Dude!, I have a Red shoe on my right foot, and a Red on my left foot
Ted : Dude!, I have a Red shoe on my right foot, and a Red on my left foot
當(dāng)Dude類包含引用類型屬性Shoe的時(shí)候,在托管堆上的情況是這樣的:
拷貝后,2個(gè)Dude的Shoe類型的屬性指向了同一個(gè)托管堆內(nèi)的Shoe實(shí)例,改變Shoe的值會(huì)同時(shí)影響到2個(gè)Dude。
很顯然,這不是我們期望的完全拷貝,如何做到完全拷貝呢?
--實(shí)現(xiàn)ICloneable接口
ICloneable接口的Clone()方法,允許我們?cè)诳截惖臅r(shí)候,進(jìn)行一些自定義設(shè)置。
讓引用類Shoe實(shí)現(xiàn)ICloneable接口。
public class Shoe : ICloneable{ public string Color; public object Clone() {Shoe newShoe = new Shoe();newShoe.Color = Color.Clone() as string;return newShoe; }}
以上,Shoe的string類型屬性Color之所以可以使用Color.Clone()方法,是因?yàn)閟tring也實(shí)現(xiàn)了ICloneable接口;又由于Clone()返回類型是object,所以,在使用Color.Clone()方法之后,需要把object轉(zhuǎn)換成string類型。
現(xiàn)在,在Dude類的CopyDude()方法中,當(dāng)拷貝Shoe類型屬性的時(shí)候,就可以使用Shoe獨(dú)有的拷貝方法Clone()。
public Dude CopyDude(){ Dude newPerson = new Dude(); newPerson.Name = Name; newPerson.LeftShoe = LeftShoe.Clone() as Shoe; newPerson.RightShoe = RightShoe.Clone() as Shoe; return newPerson;}
客戶端程序:
public static void Main(){ Dude Bill = new Dude(); Bill.Name = "Bill"; Bill.LeftShoe = new Shoe(); Bill.RightShoe = new Shoe(); Bill.LeftShoe.Color = Bill.RightShoe.Color = "Blue"; Dude Ted = Bill.CopyDude(); Ted.Name = "Ted"; Ted.LeftShoe.Color = Ted.RightShoe.Color = "Red"; Console.WriteLine(Bill.ToString()); Console.WriteLine(Ted.ToString()); }
輸出結(jié)果:
Bill : Dude!, I have a Blue shoe on my right foot, and a Blue on my left foot
Ted : Dude!, I have a Red shoe on my right foot, and a Red on my left foot
這正是我們期望的完全拷貝!
完全拷貝,托管堆上的情況是這樣的:
當(dāng)然也可以讓同時(shí)包含值類型和引用類型成員,同時(shí)需要拷貝的類實(shí)現(xiàn)ICloneable接口。
public class Dude: ICloneable{ public string Name; public Shoe RightShoe; public Shoe LeftShoe; public override string ToString() {return (Name + " : Dude!, I have a " + RightShoe.Color + " shoe on my right foot, and a " + LeftShoe.Color + " on my left foot."); } #region ICloneable Members public object Clone() {Dude newPerson = new Dude();newPerson.Name = Name.Clone() as string;newPerson.LeftShoe = LeftShoe.Clone() as Shoe;newPerson.RightShoe = RightShoe.Clone() as Shoe; return newPerson; } #endregion}
客戶端調(diào)用:
public static void Main(){ Class1 pgm = new Class1(); Dude Bill = new Dude(); Bill.Name = "Bill"; Bill.LeftShoe = new Shoe(); Bill.RightShoe = new Shoe(); Bill.LeftShoe.Color = Bill.RightShoe.Color = "Blue"; Dude Ted = Bill.Clone() as Dude; Ted.Name = "Ted"; Ted.LeftShoe.Color = Ted.RightShoe.Color = "Red"; Console.WriteLine(Bill.ToString()); Console.WriteLine(Ted.ToString()); }
輸出結(jié)果:
Bill : Dude!, I have a Blue shoe on my right foot, and a Blue on my left foot.
Ted : Dude!, I have a Red shoe on my right foot, and a Red on my left foot.
也是我們期望的完全拷貝!
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
相關(guān)文章:
1. ASP.NET Core依賴注入DI容器的方法實(shí)現(xiàn)2. ASP.NET MVC實(shí)現(xiàn)城市或車(chē)型三級(jí)聯(lián)動(dòng)3. ASP.NET延遲調(diào)用或多次調(diào)用第三方Web API服務(wù)4. ASP.NET MVC使用Session會(huì)話保持表單狀態(tài)5. ASP.NET泛型三之使用協(xié)變和逆變實(shí)現(xiàn)類型轉(zhuǎn)換6. 利用VS2019創(chuàng)建Web項(xiàng)目并發(fā)送到IIS及IIS與ASP.NET配置教程7. ASP.NET MVC使用typeahead.js實(shí)現(xiàn)輸入智能提示功能8. asp.net core 中的Jwt(Json Web Token)的使用詳解9. ASP.NET MVC實(shí)現(xiàn)樹(shù)形導(dǎo)航菜單10. ASP.NET MVC使用Identity增刪改查用戶
