好像園內比較多博客對 Shallow、Deep Cloning的翻譯是深拷貝、淺拷貝,當時我懵了,這個叫法怎么怪怪的。
就好像看軍情觀察室,臺灣評論員,導彈叫飛彈。
至于它們的區別,一張圖就可以解釋。
這兩個概念,經常對一些對象操作時,忘了自己使用的是shallow 還是deep,而搞到神經大條。
MSDN的解釋是:
Clone can be implemented either as a deep copy or a shallow copy.In a deep copy, all objects are duplicated; whereas, in a shallow copy, only the top-level objects are duplicated and the lower levels contain references.http://msdn.microsoft.com/zh-cn/library/system.icloneable.clone.aspx
Shallow copy by creating a new object, and then copying the nonstatic fields of the current object to the new object.If a field is a value type, a bit-by-bit copy of the field is performed.If a field is a reference type, the reference is copied but the referred object is not; therefore, the original object and its clone refer to the same object.http://msdn.microsoft.com/zh-cn/library/system.object.memberwiseclone.aspx
先說一下string,因為測試代碼用了string對象:
string testClone = "a測試"; testClone = "b測試"; Console.WriteLine("testClone:" + testClone);
.entrypoint // 代碼大小 37 (0x25) .maxstack 2 .locals init ([0] string testClone) IL_0000: nop IL_0001: ldstr bytearray (61 00 4B 6D D5 8B ) // a.Km.. IL_0006: stloc.0 IL_0007: ldstr bytearray (62 00 4B 6D D5 8B ) // b.Km.. IL_000c: stloc.0 IL_000d: ldstr bytearray (74 00 65 00 73 00 74 00 43 00 6C 00 6F 00 6E 00 // t.e.s.t.C.l.o.n. 65 00 1A FF ) // e... IL_0012: ldloc.0 IL_0013: call string [mscorlib]System.String::Concat(string, string) IL_0018: call void [mscorlib]System.Console::WriteLine(string) IL_001d: nop IL_001e: call int32 [mscorlib]System.Console::Read() IL_0023: pop IL_0024: ret
testClone = "b測試";創建了"b測試"對象,并將該對象指引賦值給 testClone;
String 對象稱為不可變的(只讀),因為一旦創建了該對象,就不能修改該對象的值。看來似乎修改了 String 對象的方法實際上是返回一個包含修改內容的新 String 對象。如果需要修改字符串對象的實際內容,請使用 System.Text.StringBuilder 類。
想查看IL指令,請看中英文對照表:
CN-http://www.cnblogs.com/flyingbirds123/archive/2011/01/29/1947626.html;
ES-http://en.csharp-online.net/CIL_Instruction_Set.
下面是我的測試代碼:
CouponConfig couponClone = new CouponConfig() { Amount = 10, CouponName = "測試1", ListTest = new List<string> { "a", "b" } }; CouponConfig coupon1Clone = couponClone; CouponConfig coupon2Clone = (CouponConfig)couponClone.Clone(); CouponConfig coupon3Clone = null; using (Stream objectStream = new MemoryStream()) { IFormatter formatter = new BinaryFormatter(); formatter.Serialize(objectStream, couponClone); objectStream.Seek(0, SeekOrigin.Begin); coupon3Clone = (CouponConfig)formatter.Deserialize(objectStream); } couponClone.CouponName = "測試2"; coupon2Clone.ListTest.Add("c"); coupon3Clone.ListTest.Add("d"); Console.WriteLine("couponClone:" + couponClone.CouponName); Console.WriteLine("coupon2Clone:" + coupon2Clone.CouponName); foreach (string c in couponClone.ListTest) { Console.Write(c); } Console.WriteLine(""); foreach (string c in coupon2Clone.ListTest) { Console.Write(c); } Console.WriteLine(""); foreach (string c in coupon3Clone.ListTest) { Console.Write(c); } Console.WriteLine(""); Console.Read();
[Serializable] public class CouponConfig : ICloneable { private CouponConfig config; public CouponConfig Config { get { if (config == null) { config = null; } return config; } } public CouponConfig() { } #region Model private int _amount; private string _couponname; private List<string> listTest; public string CouponName { get { return _couponname; } set { _couponname = value; } } public List<string> ListTest { get { return listTest; } set { listTest = value; } } public int Amount { set { _amount = value; } get { return _amount; } } #endregion Model public object Clone() { return this.MemberwiseClone(); } }
運行結果是:
接下來思考一下吧,datatable的Copy、Clone是什么cloning呢?
DataTable dt = new DataTable(); DataTable dtcopy = dt.Copy(); DataTable dtclone = dt.Clone();
當然最常見的是Ling to sql 的操作,where、OrderBy···,是什么cloning呢?
對象類實現了ICloneable就可以使用this.MemberwiseClone(); 實現shallow cloning;
也可以自己寫clone
public class Person : ICloneable { public string Name; public Person Spouse; public object Clone() { Person p = new Person(); p.Name = this.Name; if (this.Spouse != null) p.Spouse = (Person)this.Spouse.Clone(); return p; } }
Deep Cloning可以使用 Serialization
using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; public static class ObjectCopier { /// <summary> /// Perform a deep Copy of the object. /// </summary> /// <typeparam name="T">The type of object being copied.</typeparam> /// <param name="source">The object instance to copy.</param> /// <returns>The copied object.</returns> public static T Clone<T>(T source) { if (!typeof(T).IsSerializable) { throw new ArgumentException("The type must be serializable.", "source"); } // Don't serialize a null object, simply return the default for that object if (Object.ReferenceEquals(source, null)) { return default(T); } IFormatter formatter = new BinaryFormatter(); Stream stream = new MemoryStream(); using (stream) { formatter.Serialize(stream, source); stream.Seek(0, SeekOrigin.Begin); return (T)formatter.Deserialize(stream); } } }
原文鏈接:http://www.cnblogs.com/daihuiquan/archive/2013/02/14/2910657.html
文章列表
留言列表