最近開發中對泛型資料進行排序,但是還需要用到未經處理資料,所以就複製了該對象到另一個對象,忘記了參考型別是傳地址的,所以出了bug,轉貼一篇文章,記錄一下自己的錯誤。
C# 支援兩種類型:“實值型別”和“參考型別”。
實值型別(Value Type)(如 char、int 和 float)、枚舉類型和結構類型。
參考型別(Reference Type) 包括類 (Class) 類型、介面類型、委託類型和數群組類型。
如何來劃分它們?
以它們在電腦記憶體中如何分配來劃分
實值型別與參考型別的區別?
1,實值型別的變數直接包含其資料,
2,參考型別的變數則儲存物件引用。
對於參考型別,兩個變數可能引用同一個對象,因此對一個變數的操作可能影響另一個變數所引用的對象。對於實值型別,每個變數都有自己的資料副本,對一個變數的操作不可能影響另一個變數。
實值型別隱式繼承自System.ValueType 所以不能顯示讓一個結構繼承一個類,C#不支援多繼承
堆棧(stack)是一種先進先出的資料結構,在記憶體中,變數會被分配在堆棧上來進行操作。
堆(heap)是用於為類型執行個體(對象)分配空間的記憶體地區,在堆上建立一個對象,
會將對象的地址傳給堆棧上的變數(反過來叫變數指向此對象,或者變數引用此對象)。
關於對象複製的所設計到知識點
淺拷貝:是指將對象中的所有欄位逐字複雜到一個新對象
對實值型別欄位只是簡單的拷貝一個副本到目標對象,改變目標對象中實值型別欄位的值不會反映到原始對象中,因為拷貝的是副本
對引用型欄位則是指拷貝他的一個引用到目標對象。改變目標對象中參考型別欄位的值它將反映到原始對象中,因為拷貝的是指向堆是上的一個地址
深拷貝:深拷貝與淺拷貝不同的是對於引用欄位的處理,深拷貝將會在新對象中建立一個新的對象和
原始對象中對應欄位相同(內容相同)的欄位,也就是說這個引用和原始對象的引用是不同, 我們改變新
對象中這個欄位的時候是不會影響到原始對象中對應欄位的內容。
淺複製: 實現淺複製需要使用Object類的MemberwiseClone方法用於建立一個淺表副本
深複製: 須實現 ICloneable介面中的Clone方法,且需要需要複製的對象加上[Serializable]特性
class DrawBase:System.Object , ICloneable
{
public string name = "jmj";
public DrawBase()
{
}
public object Clone()
{
return this as object; //引用同一個對象
return this.MemberwiseClone(); //淺複製
return new DrawBase() as object;//深複製
}
}
class Program
{
static void Main(string[] args)
{
DrawBase rect = new DrawBase();
Console.WriteLine(rect.name);
DrawBase line = rect.Clone() as DrawBase;
line.name = "a9fs3";
Console.WriteLine(rect.name);
DrawBase ploy = line.Clone() as DrawBase;
ploy.name = "lj";
Console.WriteLine(rect.name);
Console.WriteLine(object.ReferenceEquals(line, ploy));
Console.ReadLine();
}
}
運行結果:
return this as object; //引用同一個對象
輸出:jmj
a9fs3
lj
True
return this.MemberwiseClone(); //淺複製
return new DrawBase() as object;//深複製
輸出均為: jmj
jmj
jmj
False
解釋:
return this as object 方法總是引用同一個對象,因此相應的堆記憶體上的值會改變!
後兩種方法都是對對象的複製,區別在於複製的類別不同:深複製會複製整個填充的對象,包括該對象中其他參考型別和實值型別的值;而淺複製只複製了一個對象中所有引用,它沒有值的複製,通過引用它們的其他對象的引用來共用它們。
兩篇文章原文:http://www.cnblogs.com/huangting2009/archive/2009/03/13/1410634.html
還有:http://blog.csdn.net/ifooler/archive/2007/05/06/1598452.aspx