例说C#深拷贝与浅拷贝

一开始,先对C#深拷贝与浅拷贝知识做个简单的总结。

无论是浅拷贝与深拷贝,C#都将源对象中的所有字段复制到新的对象中。不过,对于值类型字段,引用类型字段以及字符串类型字段的处理,两种拷贝方式存在一定的区别(见下表)。

下面给出完整的演示代码。

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace DeepCloneExp
{
    class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person() { Name="tiana0",Age=20,Job=new Job(){JobName="Coder"} };

            Person p1 = p.ShallowClone();
            Person p2 = p.DeepClone();

            Console.WriteLine("p浅拷贝-->p1;p深拷贝-->p2");

            Console.WriteLine("p修改前:p.Name={0},p.Age={1},p.Job.JobName={2}", p.Name, p.Age, p.Job.JobName);
            Console.WriteLine("p修改前:p1.Name={0},p1.Age={1},p1.Job.JobName={2}", p1.Name, p1.Age, p1.Job.JobName);
            Console.WriteLine("p修改前:p2.Name={0},p2.Age={1},p2.Job.JobName={2}", p2.Name, p2.Age, p2.Job.JobName);

            //修改p的所有字段值
            p.Name = "tiana10000";
            p.Age = 28;
            p.Job.JobName = "Manager";

            Console.WriteLine();

            Console.WriteLine("p修改后:p.Name={0},p.Age={1},p.Job.JobName={2}", p.Name, p.Age, p.Job.JobName);
            Console.WriteLine("p修改后:p1.Name={0},p1.Age={1},p1.Job.JobName={2}", p1.Name, p1.Age, p1.Job.JobName);
            Console.WriteLine("p修改后:p2.Name={0},p2.Age={1},p2.Job.JobName={2}", p2.Name, p2.Age, p2.Job.JobName);
        }
    }

    [Serializable]
    class Person:ICloneable 
    {
        public int Age { get; set; }  //值类型字段
        public string Name { get; set; }  //字符串
        public Job Job { get; set; }  //引用类型字段

        //深拷贝
        public Person DeepClone()
        {
            using (Stream objectStream = new MemoryStream())
            {
                IFormatter formatter = new BinaryFormatter();
                formatter.Serialize(objectStream,this);
                objectStream.Seek(0, SeekOrigin.Begin);
                return formatter.Deserialize(objectStream) as Person;
            }
        }

        public object Clone()
        {
            return this.MemberwiseClone();
        }

        //浅拷贝
        public Person ShallowClone()
        {
            return this.Clone() as Person;
        }
    }

    [Serializable]
    public class Job
    {
        public string JobName { get; set; }
        public override string ToString()
        {
            return this.JobName;
        }
    }
}

运行程序,得到以下结果:

先来看看结果,很明显,当源对象改变时,副本只有浅拷贝这种情况下的引用类型字段的值会一起变化,与前面给出的结论一致(不记得的话,麻烦再看一下表格)。

 

对于演示代码,仅补充说明: Person 类与Job类均需添加标志[Serializable],否则运行时会报错。

好了,就扯到这里了。再见

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#的序列化和反序列化是将对象转换为二进制数据或将二进制数据转换为对象的过程。在C#中,可以使用BinaryFormatter、XmlSerializer、DataContractSerializer等多种方式进行序列化和反序列化。 深拷贝浅拷贝用于复制对象。浅拷贝只复制对象的引用,而不会复制对象的实际内容。深拷贝则会完全复制对象的内容,包括引用类型的成员变量。 在C#中,可以通过实现ICloneable接口来实现浅拷贝。对于深拷贝,则需要自己手动实现一个递归复制对象的方法。 下面是一个示例代码,演示了如何进行序列化、反序列化以及深拷贝浅拷贝: ```csharp using System; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Xml.Serialization; [Serializable] public class Person : ICloneable { public string Name { get; set; } public int Age { get; set; } public Address Address { get; set; } public object Clone() { return new Person { Name = Name, Age = Age, Address = (Address)Address?.Clone() }; } } [Serializable] public class Address : ICloneable { public string City { get; set; } public string Street { get; set; } public object Clone() { return new Address { City = City, Street = Street }; } } public static class SerializationHelper { public static byte[] SerializeToBinary(object obj) { using (var ms = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(ms, obj); return ms.ToArray(); } } public static T DeserializeFromBinary<T>(byte[] data) { using (var ms = new MemoryStream(data)) { var formatter = new BinaryFormatter(); return (T)formatter.Deserialize(ms); } } public static string SerializeToXml(object obj) { using (var writer = new StringWriter()) { var serializer = new XmlSerializer(obj.GetType()); serializer.Serialize(writer, obj); return writer.ToString(); } } public static T DeserializeFromXml<T>(string xml) { using (var reader = new StringReader(xml)) { var serializer = new XmlSerializer(typeof(T)); return (T)serializer.Deserialize(reader); } } } public static class ObjectHelper { public static T ShallowCopy<T>(this T obj) { return (T)obj.MemberwiseClone(); } public static T DeepCopy<T>(this T obj) { using (var ms = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(ms, obj); ms.Position = 0; return (T)formatter.Deserialize(ms); } } } // 示例代码 var person1 = new Person { Name = "Tom", Age = 30, Address = new Address { City = "Beijing", Street = "Chang'an Avenue" } }; // 深拷贝 var person2 = person1.DeepCopy(); person2.Name = "Jerry"; person2.Address.City = "Shanghai"; Console.WriteLine($"person1.Name={person1.Name}, person1.Address.City={person1.Address.City}"); Console.WriteLine($"person2.Name={person2.Name}, person2.Address.City={person2.Address.City}"); // 浅拷贝 var person3 = person1.ShallowCopy(); person3.Name = "John"; person3.Address.City = "Guangzhou"; Console.WriteLine($"person1.Name={person1.Name}, person1.Address.City={person1.Address.City}"); Console.WriteLine($"person3.Name={person3.Name}, person3.Address.City={person3.Address.City}"); // 序列化和反序列化 var data = SerializationHelper.SerializeToBinary(person1); var person4 = SerializationHelper.DeserializeFromBinary<Person>(data); Console.WriteLine($"person1.Name={person1.Name}, person1.Address.City={person1.Address.City}"); Console.WriteLine($"person4.Name={person4.Name}, person4.Address.City={person4.Address.City}"); var xml = SerializationHelper.SerializeToXml(person1); var person5 = SerializationHelper.DeserializeFromXml<Person>(xml); Console.WriteLine($"person1.Name={person1.Name}, person1.Address.City={person1.Address.City}"); Console.WriteLine($"person5.Name={person5.Name}, person5.Address.City={person5.Address.City}"); ``` 输出结果: ``` person1.Name=Tom, person1.Address.City=Beijing person2.Name=Jerry, person2.Address.City=Shanghai person1.Name=Tom, person1.Address.City=Guangzhou person3.Name=John, person3.Address.City=Guangzhou person1.Name=Tom, person1.Address.City=Beijing person4.Name=Tom, person4.Address.City=Beijing person1.Name=Tom, person1.Address.City=Beijing person5.Name=Tom, person5.Address.City=Beijing ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值