C# 支持兩種類型:“值類型”和“引用類型”。
值類型(Value Type)(如 char、int 和 float)、枚舉類型和結構類型。
引用類型(Reference Type) 包括類 (Class) 類型、接口類型、委托類型和數組類型。
如何來划分它們?
以它們在計算機內存中如何分配來划分
值類型與引用類型的區別?
1,值類型的變量直接包含其數據,
2,引用類型的變量則存儲對象引用。
對於引用類型,兩個變量可能引用同一個對象,因此對一個變量的操作可能影響另一個變量所引用的對象。對於值類型,每個變量都有自己的數據副本,對一個變量的操作不可能影響另一個變量。
值類型隱式繼承自System.ValueType 所以不能顯示讓一個結構繼承一個類,C#不支持多繼承
堆棧(stack)是一種先進先出的數據結構,在內存中,變量會被分配在堆棧上來進行操作。
堆(heap)是用於為類型實例(對象)分配空間的內存區域,在堆上創建一個對象,
會將對象的地址傳給堆棧上的變量(反過來叫變量指向此對象,或者變量引用此對象)。
關於對象克隆的所設計到知識點
- 淺拷貝:是指將對象中的所有字段逐字復雜到一個新對象
對值類型字段只是簡單的拷貝一個副本到目標對象,改變目標對象中值類型字段的值不會反映到原始對象中,因為拷貝的是副本
對引用型字段則是指拷貝他的一個引用到目標對象。改變目標對象中引用類型字段的值它將反映到原始對象中,因為拷貝的是指向堆是上的一個地址
- 深拷貝:深拷貝與淺拷貝不同的是對於引用字段的處理,深拷貝將會在新對象中創建一個新的對象和
原始對象中對應字段相同(內容相同)的字段,也就是說這個引用和原始對象的引用是不同, 我們改變新
對象中這個字段的時候是不會影響到原始對象中對應字段的內容。
- 淺復制: 實現淺復制需要使用Object類的MemberwiseClone方法用於創建一個淺表副本
- 深復制: 須實現 ICloneable接口中的Clone方法,且需要需要克隆的對象加上[Serializable]特性
namespace DeepCopy { class DrawBase : System.Object, ICloneable { public List<string> listName = new List<string>(); public string name = "old"; 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 = "new"; line.listName.Add("123"); Console.WriteLine(rect.name); Console.WriteLine(rect.listName.Count); Console.ReadLine(); } } }
當return this as object;
輸出:old,new,1
說明:方法總是引用同一個對象,因此相應的堆內存上的值會改變
當return this.MemberwiseClone();
輸出:old,old,1
說明:對於內部的Class的對象和數組,會Copy地址一份。[從而改變B時,A也被改變了]而對於其它內置的int/string/Enum/struct/object類型,則進行值copy。
當return new DrawBase() as object;
輸出:old,old,0
說明:完全是創建一個新對象
總結:
淺拷貝:是指將對象中的所有字段逐字復雜到一個新對象。
對值類型字段只是簡單的拷貝一個副本到目標對象,改變目標對象中值類型字段的值不會反映到原始對象中,因為拷貝的是副本;
對引用型字段則是指拷貝他的一個引用到目標對象。改變目標對象中引用類型字段的值它將反映到原始對象中,因為拷貝的是指向堆是上的一個地址;
深拷貝:深拷貝與淺拷貝不同的是對於引用字段的處理,深拷貝將會在新對象中創建一個新的對象和原始對象中對應字段相同(內容相同)的字段,也就是說這個引用和原始對象的引用是不同, 我們改變新對象中這個字段的時候是不會影響到原始對象中對應字段的內容。