ASP.NET堆和棧三之引用類型對象拷貝和內(nèi)存分配
".NET的堆和棧"系列:
ASP.NET堆和棧二之值類型和引用類型參數(shù)傳遞和內(nèi)存分配
ASP.NET堆和棧三之引用類型對象拷貝和內(nèi)存分配
ASP.NET堆和棧四之對托管和非托管資源垃圾的回收和內(nèi)存分配
在" ASP.NET堆和棧一之基本概念和值類型內(nèi)存分配"中,了解了"堆"和"棧"的基本概念,以及值類型的內(nèi)存分配。我們知道:當執(zhí)行一個方法的時候,值類型實例會在"棧"上分配內(nèi)存,而引用類型實例會在"堆"上分配內(nèi)存,當方法執(zhí)行完畢,"棧"上的實例由操作系統(tǒng)自動釋放,"堆"上的實例由.NET Framework的GC進行回收。
在" ASP.NET堆和棧二之值類型和引用類型參數(shù)傳遞和內(nèi)存分配"中,我們了解了值類型參數(shù)和引用類型參數(shù)在傳遞時的內(nèi)存分配情況。
而本篇的重點要放在:引用類型對象拷貝以及內(nèi)存分配。
引用類型對象拷貝 成員都是值類型
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
以上,當引用類型的屬性、成員都是值類型的時候,拷貝是完全拷貝。

引用類型對象拷貝 包含引用類型成員
把Shoe由struct值類型改成引用類型class。
public class Shoe
{
public string Color;
}再次運行,輸出結(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
當Dude類包含引用類型屬性Shoe的時候,在托管堆上的情況是這樣的:

拷貝后,2個Dude的Shoe類型的屬性指向了同一個托管堆內(nèi)的Shoe實例,改變Shoe的值會同時影響到2個Dude。
很顯然,這不是我們期望的完全拷貝,如何做到完全拷貝呢?
--實現(xiàn)ICloneable接口
ICloneable接口的Clone()方法,允許我們在拷貝的時候,進行一些自定義設置。
讓引用類Shoe實現(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()方法,是因為string也實現(xiàn)了ICloneable接口;又由于Clone()返回類型是object,所以,在使用Color.Clone()方法之后,需要把object轉(zhuǎn)換成string類型。
現(xiàn)在,在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());
}輸出結(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
這正是我們期望的完全拷貝!
完全拷貝,托管堆上的情況是這樣的:

當然也可以讓同時包含值類型和引用類型成員,同時需要拷貝的類實現(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.
也是我們期望的完全拷貝!
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。如果你想了解更多相關內(nèi)容請查看下面相關鏈接
相關文章
WPF實現(xiàn)ScrollViewer滾動到指定控件處
這篇文章主要為大家詳細介紹了WPF實現(xiàn)ScrollViewer滾動到指定控件處,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06
asp.net下配置數(shù)據(jù)源時出現(xiàn): 未將對象引用設置到對象的實例。
未將對象引用設置到對象的實例的一個另類解決方法2008-06-06
ASP.NET中利用Segments取得URL的文件名的一種方法分享
在ASP.NET中,取得請求頁的URL地址有多種方式,其中有一種方式取得網(wǎng)頁文件名。2011-09-09
asp.net下模態(tài)對話框關閉之后繼續(xù)執(zhí)行服務器端代碼的問題
asp.net下模態(tài)對話框關閉之后繼續(xù)執(zhí)行服務器端代碼的問題...2007-04-04
HTTP協(xié)議下用Web Service上傳大文件的解決方案
HTTP協(xié)議下用Web Service上傳大文件的解決方案...2007-04-04
Repeater控件動態(tài)變更列(Header,Item和Foot)信息實現(xiàn)思路
需求開發(fā)一個小報表,顯示最近五個月的summary的數(shù)量統(tǒng)計,報表會隨月份的變化而變化,接下來為大家詳細介紹下實現(xiàn)方法,感興趣的各位不要錯過了哈2013-03-03
DataTable數(shù)據(jù)導出成Excel文件的小例子
DataTable數(shù)據(jù)導出成Excel文件的小例子,需要的朋友可以參考一下2013-04-04

