ASP.NET堆和棧三之引用類型對象拷貝和內存分配
".NET的堆和棧"系列:
在" ASP.NET堆和棧一之基本概念和值類型內存分配"中,了解了"堆"和"棧"的基本概念,以及值類型的內存分配。我們知道:當執行一個方法的時候,值類型實例會在"棧"上分配內存,而引用類型實例會在"堆"上分配內存,當方法執行完畢,"棧"上的實例由操作系統自動釋放,"堆"上的實例由.NET Framework的GC進行回收。
在" ASP.NET堆和棧二之值類型和引用類型參數傳遞和內存分配"中,我們了解了值類型參數和引用類型參數在傳遞時的內存分配情況。
而本篇的重點要放在:引用類型對象拷貝以及內存分配。
引用類型對象拷貝 成員都是值類型
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()); }
輸出結果:
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
以上,當引用類型的屬性、成員都是值類型的時候,拷貝是完全拷貝。
引用類型對象拷貝 包含引用類型成員
把Shoe由struct值類型改成引用類型class。
public class Shoe{ public string Color;}
再次運行,輸出結果:
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
當Dude類包含引用類型屬性Shoe的時候,在托管堆上的情況是這樣的:
拷貝后,2個Dude的Shoe類型的屬性指向了同一個托管堆內的Shoe實例,改變Shoe的值會同時影響到2個Dude。
很顯然,這不是我們期望的完全拷貝,如何做到完全拷貝呢?
--實現ICloneable接口
ICloneable接口的Clone()方法,允許我們在拷貝的時候,進行一些自定義設置。
讓引用類Shoe實現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()方法,是因為string也實現了ICloneable接口;又由于Clone()返回類型是object,所以,在使用Color.Clone()方法之后,需要把object轉換成string類型。
現在,在Dude類的CopyDude()方法中,當拷貝Shoe類型屬性的時候,就可以使用Shoe獨有的拷貝方法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()); }
輸出結果:
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
這正是我們期望的完全拷貝!
完全拷貝,托管堆上的情況是這樣的:
當然也可以讓同時包含值類型和引用類型成員,同時需要拷貝的類實現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}
客戶端調用:
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()); }
輸出結果:
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.
也是我們期望的完全拷貝!
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對的支持。如果你想了解更多相關內容請查看下面相關鏈接
相關文章:
1. ASP.Net Core(C#)創建Web站點的實現2. ASP.NET MVC前臺動態添加文本框并在后臺使用FormCollection接收值3. 使用EF Code First搭建簡易ASP.NET MVC網站并允許數據庫遷移4. ASP.NET Core 依賴注入生命周期示例詳解5. 使用本機IIS?Express開發Asp.Net?Core應用圖文教程6. ASP.NET MVC視圖頁使用jQuery傳遞異步數據的幾種方式詳解7. ASP.NET MVC使用Quartz.NET執行定時任務8. ASP.NET MVC使用jQuery ui的progressbar實現進度條9. asp.net core 中的Jwt(Json Web Token)的使用詳解10. ASP.NET MVC增加一條記錄同時添加N條集合屬性所對應的個體
