c#中的對象大體分為值類型和引用類型,值類型大致包括 int, struct等,引用類型大致包括 自定義Class,object 等。string屬於特殊的引用類型,不在本文的討論之內。
值類型直接存儲對象,而引用類型存儲對象的地址,在對引用類型進行復制的時候,也只是復制對象的地址。
完全復制一個引用類型對象主要有幾種方法:
1.添加一個Copy函數,進行拷貝(如果字段為引用類型,需要循環添加Copy函數,這樣情況會變的十分復雜。)
namespace ConsoleApplication1 { class User { public string Name { get; set; } public string Sex { get; set; } public House Home { get; set; } public User Copy() { User newUser = (User)this.MemberwiseClone(); newUser.Home = this.Home.Copy(); return newUser; } } class House { public string Address { get; set; } public House Copy() { return (House)this.MemberwiseClone(); } } class Program { static void Main(string[] args) { User a = new User(); a.Name = "A"; a.Home = new House() { Address = "長江路" }; User b = a.Copy(); b.Name = "B"; b.Home.Address = "黃河路"; Console.WriteLine(a.Name); Console.WriteLine(a.Home.Address); Console.ReadLine(); } } }
2.利用序列化反序列化(對性能會有殺傷)
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading.Tasks; namespace Test { class Program { static void Main(string[] args) { Test t1 = new Test(); Console.WriteLine(t1.list.Count); Test t2 = (Test)Clone(t1); t2.list.Add(""); Console.WriteLine(t2.list.Count); Console.WriteLine(t1.list.Count); Console.ReadLine(); } public static object Clone(object obj) { BinaryFormatter bf = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); bf.Serialize(ms, obj); ms.Position = 0; return (bf.Deserialize(ms)); ; } } [Serializable] public class Test { public List<string> list = new List<string>(); } }
3.利用反射(測試了一個網上的接口可用,但是對性能殺傷和序列化反序列化相當,而且可能對代碼混淆有一定影響。 https://www.cnblogs.com/zhili/p/DeepCopy.html)
最后附上微軟文檔:
https://docs.microsoft.com/zh-cn/dotnet/api/system.object.memberwiseclone?redirectedfrom=MSDN&view=netframework-4.7.2#System_Object_MemberwiseClone