一、浅拷贝:指对象的字段被拷贝,而字段引用的对象不会被拷贝,拷贝对象和原对象仅仅是引用名称有所不同,但是它们共用一份实体。对任何一个对象的改变,都会影响到另外一个对象。大部分的引用类型,实现的都是浅拷贝,引用类型对象之间的赋值,就是复制一个对象引用地址的副本,而指向的对象实例仍然是同一个。
- 给字段挨个赋值(缺点是没有扩展性)
- .NET里面也提供了一个方法MemberwiseClone,这个方法默认就是返回当前对象的副本,所以浅拷贝可以这样实现:
public People ShallowCopy() { return (People)this.MemberwiseClone(); }
前台调用如下:
public class Employee { public string Name { get; set; } public Dog Dog { get; set; } // 新增复杂对象 public Employee Copy() => this.MemberwiseClone() as Employee; } public class Dog { public string Name { get; set; } } Dog dog = new Dog() { Name = "小狗钱钱" }; Employee e1 = new Employee() { Name = "张三", Dog = dog }; Employee e2 = e1.Copy(); e2.Name = "李四"; Console.WriteLine(e1.Name); // 张三 Console.WriteLine(e2.Name); // 李四 Console.WriteLine(ReferenceEquals(e1, e2)); // False // 新增比较 e1.Dog.Name = "小狗"; Console.WriteLine(e1.Dog.Name); // 小狗 Console.WriteLine(e2.Dog.Name); // 小狗 Console.WriteLine(ReferenceEquals(e1.Dog, e2.Dog)); // True
二、深拷贝:指对象的子段被拷贝,同时字段引用的对象也进行了拷贝。深拷贝创建的是整个源对象的结构,拷贝对象和原对象相互独立,不共享任何实例数据,修改一个对象不会影响到另一个对象。值类型之间的赋值操作,执行的就是深拷贝。
方式一: 使用二进制流
using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; /// <summary> /// 参考 http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx /// </summary> public static class ObjectCopier { public static T Clone<T>(T source) { if (!typeof(T).IsSerializable) { throw new ArgumentException("The type must be serializable.", "source"); } 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); } } }
方式二 使用序列化与反序列化
public static T CloneJson<T>(this T source) { if (Object.ReferenceEquals(source, null)) { return default(T); } var deserializeSettings = new JsonSerializerSettings {ObjectCreationHandling = ObjectCreationHandling.Replace}; return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source), deserializeSettings); }
方式三 使用反射
public static T DeepCopyByReflect<T>(T obj) { //如果是字符串或值类型则直接返回 if (obj is string || obj.GetType().IsValueType) return obj; object retval = Activator.CreateInstance(obj.GetType()); FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); foreach (FieldInfo field in fields) { try { field.SetValue(retval, DeepCopyByReflect(field.GetValue(obj))); } catch { } } return (T)retval; }
方式四 使用XML序列化与反序列化
public static T DeserializeXML<T>(string xmlData) where T:new() { if (string.IsNullOrEmpty(xmlData)) return default(T); TextReader tr = new StringReader(xmlData); T DocItms = new T(); XmlSerializer xms = new XmlSerializer(DocItms.GetType()); DocItms = (T)xms.Deserialize(tr); return DocItms == null ? default(T) : DocItms; }
标签:克隆,对象,Dog,public,new,NET,拷贝,Name From: https://www.cnblogs.com/gougou1981/p/16972419.html