C#淺拷貝和深拷貝
所謂的物件拷貝,其實就是為物件建立副本,C#中將拷貝分為兩種,分別為淺拷貝和深拷貝;
所謂淺拷貝就是將物件中的所有欄位複製到新的副本物件中;淺拷貝對於值型別與引用型別的方式有區別,值型別欄位的值被複制到副本中後,在副本中的修改不會影響源物件對應的值;然而對於引用型別的欄位被複制到副本中的卻是引用型別的引用,而不是引用的物件,在副本中對引用型別的欄位值被修改後,源物件的值也將被修改。
深拷貝也同樣是將物件中的所有欄位複製到副本物件中,但是,無論物件的值型別欄位或者引用型別欄位,都會被重新建立並複製,對於副本的修改,不會影響到源物件的本身;
當然,無論是哪種拷貝,微軟都建議使用型別繼承ICloneable介面的方式明確告訴呼叫者,該物件是否可用被拷貝。當然了,ICloneable介面只提供了一個宣告為Clone的方法,我們可以根據需求在Clone的方法內實現淺拷貝或者是深拷貝,下面我們進行一段淺拷貝的案例,程式碼如下
class Student : ICloneable
{
public string IDCode { get; set; }
public int Age { get; set; }
public Grent Grent { get; set; }
#region 拷貝主體
public object Clone()
{
return this.MemberwiseClone();
//throw new NotImplementedException();
}
#endregion
}
class Grent
{
public string Name { get; set; }
public override string ToString()
{
return this.Name;
}
}
呼叫
Student stu1 = new Student()
{
IDCode = "lily",
Age = 24,
Grent = new Grent() { Name="五年三班"}
};
Student stu2 = stu1.Clone() as Student;
if (stu2 == null) {
Console.WriteLine("轉換失敗");
Console.ReadKey();
return;
}
Console.WriteLine(stu2.IDCode);
Console.WriteLine(stu2.Age);
Console.WriteLine(stu2.Grent.ToString());
Console.WriteLine("重新為stu1賦值");
stu1.IDCode = "Anagle";
stu1.Age += 10;
stu1.Grent.Name = "六年二班";
Console.WriteLine(stu2.IDCode);
Console.WriteLine(stu2.Age);
Console.WriteLine(stu2.Grent.ToString());
Console.ReadKey();
輸出結果為:
lily
24
五年三班
重新為stu1賦值
lily
24
六年二班
這裡我們需要注意一點Student中的IDCode屬性是string型別,理論上string型別是引用型別,但是由於該引用型別的特殊性,Object.MemberwiseClone方法仍舊為他建立了副本,也就是說,在淺拷貝過程中,我們應該將字串看成值型別;
因為Student中的Grent是引用型別,所以在stu1中的Grent的Name被改變的同時,副本stu2中的Grent的Name也同樣被改變。
Student的深拷貝有多鍾實現方法,最簡單的方法是手動對欄位諑個賦值,但是這種方法容易出錯,也就是說,如果型別的欄位發生變化或有增減時,那麼該拷貝方法也就要發生相應的變化,所以,建議使用序列化的形式來進行深拷貝。實現程式碼如下
[Serializable]
class Student : ICloneable
{
public string IDCode { get; set; }
public int Age { get; set; }
public Grent Grent { get; set; }
#region 拷貝主體
/// <summary>
/// 深度拷貝
/// </summary>
/// <returns></returns>
public Student DeepClone() {
using (Stream objectStream = new MemoryStream()) {
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(objectStream, this);
objectStream.Seek(0,SeekOrigin.Begin);
return formatter.Deserialize(objectStream) as Student;
}
}
public object Clone()
{
return this.MemberwiseClone();
}
#endregion
}
呼叫DeepClone方法
Student stu1 = new Student()
{
IDCode = "lily",
Age = 24,
Grent = new Grent() { Name="五年三班"}
};
Student stu2 = stu1.DeepClone() as Student;
if (stu2 == null) {
Console.WriteLine("轉換失敗");
Console.ReadKey();
return;
}
Console.WriteLine(stu2.IDCode);
Console.WriteLine(stu2.Age);
Console.WriteLine(stu2.Grent.ToString());
Console.WriteLine("重新為stu1賦值");
stu1.IDCode = "Anagle";
stu1.Age += 10;
stu1.Grent.Name = "六年二班";
Console.WriteLine(stu2.IDCode);
Console.WriteLine(stu2.Age);
Console.WriteLine(stu2.Grent.ToString());
Console.ReadKey();
輸出結果為:
lily
24
五年三班
重新為stu1賦值
lily
24
五年三班
這次我們看到的結果已經很明顯了,深拷貝後,源物件的重新賦值與修改將不再導致副本物件被修改,這樣將很好的控制住引用型別的拷貝問題。相關推薦
C語言中的淺拷貝和深拷貝
淺拷貝 首先看下面這段程式碼: # include<assert.h> # include<string.h> #include <stdlib.h> typedef struct Node//定義了一個結構體 { int size; char *da
C++淺拷貝和深拷貝
C++系統提供的拷貝建構函式是淺拷貝,只是簡單的值拷貝 #include<iostream> using namespace std; class Test { public: int m_a; char *name; public: Test(const c
C#淺拷貝和深拷貝
C#中的物件拷貝問題;所謂的物件拷貝,其實就是為物件建立副本,C#中將拷貝分為兩種,分別為淺拷貝和深拷貝;所謂淺拷貝就是將物件中的所有欄位複製到新的副本物件中;淺拷貝對於值型別與引用型別的方式有區別,值型別欄位的值被複制到副本中後,在副本中的修改不會影響源物件對應的值;然而對
瞭解C# Tips淺拷貝和深拷貝(轉)
引言 C#中有兩種型別變數,一種 是值型別變數,一種是引用型別變數,對於值型別變數,深拷貝和前拷貝都是通過賦值操作符號(=)實現,其效果一致,將物件中的值型別的欄位拷貝到新的物件中.這個很容易理解。 本文重點討論引
C++的淺拷貝和深拷貝
我列舉一個例子來說吧:你正在編寫C++程式中有時後用到,操作符的過載。最能體現深層拷貝與淺層拷貝的,就是‘=’的過載。看下面一個簡單的程式:class string{char *m_str;public:string(char *s){m_str=s;}string(){
python中的淺拷貝和深拷貝
div blog deep imp class pri cnblogs 字符串 style 1.淺拷貝 copy.copy() 淺拷貝是拷貝只拷貝最外一層(這裏所說的拷貝是重新生成一個內存地址,也就是只有最外層的地址是重新生成) import copy li=[23,45
引用賦值,淺拷貝和深拷貝
lan art csdn 理解 article 淺拷貝和深拷貝 blank .net hang 三種引用: http://blog.csdn.net/XIAXIA__/article/details/41652057 深拷貝和淺拷貝的理解: http://blog.csdn
【轉】python的淺拷貝和深拷貝
end ont code append pen ron 實例 賦值 深拷貝 直接賦值:其實就是對象的引用(別名)。 淺拷貝(copy):拷貝父對象,不會拷貝對象的內部的子對象。 深拷貝(deepcopy): copy 模塊的 deepcopy 方法,完全拷貝了父對象及其
js 對象的淺拷貝和深拷貝
tex bject script cnblogs ons assign 對象 而已 obj //淺拷貝,拷貝內存塊,拷貝部門代碼不共存 var obj = { a : "a", b : "b", c : { text : "這是一個文本" } }
java淺拷貝和深拷貝
一起 head 有著 cloneabl 獨立 head對象 影響 如果 覆蓋 轉:http://blog.csdn.net/u014727260/article/details/55003402 實現clone的2點: 1,clone方法是Object類的一個方法
JavaScript中的淺拷貝和深拷貝
ons == 進行 新建 手動 一個 var javascrip 空間 淺拷貝:拷貝引用。 拷貝後的新對象和源對象都是指向同一個引用地址,因此彼此之間操作互相影響。 let a = {num:1}; let b = a; console.log(a===b); //true
Python 中的淺拷貝和深拷貝
ont () ebe ans 深拷貝 函數 port epc com 1. 列表和字典,直接賦值,都是淺拷貝,即賦值雙方指向同一地址,因為 Python 對可變對象按引用傳遞。 >>> a = [1, 2, 3] >>> b
淺拷貝和深拷貝
color using href delete del private 釋放資源 class strcpy 淺拷貝和深拷貝 在某些狀況下,類內成員變量需要動態開辟堆內存,如果實行位拷貝,也就是把對象裏的值完全復制給另一個對象,如A=B。這時,如果B中有一個成員變量指針
【iOS】淺拷貝和深拷貝
簡單 HR 除了 深淺拷貝 感謝 with 分配 指針 object 淺拷貝和深拷貝 淺拷貝即指針拷貝,可以認為是給一只狗加了一條繩子;深拷貝不但拷貝了對象的指針,還在系統中在分配了一塊內存用來存放拷貝對象的內容,可以認為是產生了一條帶繩子的新狗。即淺拷貝是兩根繩子一條狗
淺拷貝和深拷貝以及copy.copy
深淺拷貝 port log HA 都是 epc cnblogs www 就是 淺拷貝:“=” >>> a=[1,2,3]>>> b=a>>> a[1, 2, 3]>>> b[1, 2, 3]>&g
js實現淺拷貝和深拷貝
擴展運算 復制對象 數據類型 對象 return strong key stringify 循環 淺拷貝和深拷貝都只針對於像Object, Array這樣的復雜對象, 區別:淺拷貝只復制對象的第一層屬性、深拷貝可以對對象的屬性進行遞歸復制 如果數組元素是基本類型,就會拷貝一
淺談java淺拷貝和深拷貝
原來 變量 基本數據 的區別 引用數據類型 復制 值傳遞 ec2 深拷貝和淺拷貝 前言:深拷貝和淺拷貝的區別是什麽? 淺拷貝:被復制的對象的所有變量都含有原來對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。換言之, 淺拷貝僅僅復制所考慮的對象,而不復制它所引用的對
java淺拷貝和深拷貝(基礎也是很重要的)
inf n) vat 實現 技術 變量 hub -h 接口 對象的copy你興許只是懵懂,或者是並沒在意,來了解下吧。 對於的github基礎代碼https://github.com/chywx/JavaSE 最近學習c++,跟java很是相像,在慕課網學習c++也算是
初始JAVA中淺拷貝和深拷貝
exc 深度復制 tst 圖片 們的 over 地方 per 發生 1. 簡單變量的復制 public static void main(String[] args) { int a = 5; int b = a;
python 淺拷貝和深拷貝淺析
編碼過程中發現,列表a和b,初始化a,b拷貝a,b中元素值改過之後,a中元素也會跟著修改,一直以為是自己程式碼邏輯出了錯誤,最後發現這裡的坑是python中淺拷貝和深拷貝的機制 在python中,物件的屬性值有:物件id(記憶體地址),物件型別,物件值 id:唯一標識一個物件:if a