C# 集合---深拷贝三种方法(序列化,手动,反射)

深拷贝与浅拷贝(shallow copy)的区别在于,深拷贝不仅复制对象的引用,还复制对象本身及其包含的所有子对象。

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using Newtonsoft.Json;
using System.Reflection;
using System.Collections.Generic;

// 需要被深度复制的类
[Serializable] // 用于二进制序列化
    public class Person : ICloneable
    {
    public Person()
    {

    }
        public string Name { get; set; }
        public Address Address { get; set; }

        public int[] MyArray { get;  set; }
    // 方法二:手动深度复制
    public object Clone()
        {
        return new Person
        {
            Name = this.Name, // string是immutable,浅复制安全
            Address = (Address)this.Address.Clone() ,// 递归复制引用类型
            MyArray = (int[])this.MyArray.Clone()
    };
        }

        // 辅助方法,用于输出对象信息
        public override string ToString()
        {
            return $"Name: {Name}, Address: {Address},MyArray:{MyArray.Length}";
        }
    }

    [Serializable]
    public class Address : ICloneable
    {
    public Address()
    {

    }
        public string Street { get; set; }

        public object Clone()
        {
            return new Address { Street = this.Street };
        }

        public override string ToString()
        {
            return $"Street: {Street}";
        }
    }

    public class DeepCopyHelper
    {
        // 方法一:使用二进制序列化(需要[Serializable]标记)
        public static T DeepCopyUsingSerialization<T>(T original)
        {
            if (!typeof(T).IsSerializable)
                throw new ArgumentException("类型必须标记为[Serializable]", nameof(original));

            if (original == null)
                return default;

            using (var memoryStream = new MemoryStream())
            {
                IFormatter formatter = new BinaryFormatter();
                formatter.Serialize(memoryStream, original);
                memoryStream.Seek(0, SeekOrigin.Begin);
                return (T)formatter.Deserialize(memoryStream);
            }
        }

        // 方法二:使用JSON序列化(需要Newtonsoft.Json包)
        public static T DeepCopyUsingJson<T>(T original)
        {
            if (original == null)
                return default;

            string json = JsonConvert.SerializeObject(original);
            return JsonConvert.DeserializeObject<T>(json);
        }

    // 方法三:使用反射实现通用深度复制
    // 带对象跟踪的增强版本
    public static T DeepCopyUsingReflection<T>(T original)
    {
        var visited = new Dictionary<object, object>();
        return (T)CopyRecursive(original, visited);
    }

    private static object CopyRecursive(object original, Dictionary<object, object> visited)
    {
        if (original == null) return null;

        Type type = original.GetType();

        // 处理已复制过的对象
        if (visited.TryGetValue(original, out var copied))
        {
            return copied;
        }

        // 处理不可变类型
        if (type.IsPrimitive || type == typeof(string))
        {
            visited.Add(original, original);
            return original;
        }

        // 处理数组
        if (type.IsArray)
        {
            var originalArray = (Array)original;
            var elementType = type.GetElementType();
            var copiedArray = (Array)originalArray.Clone();
            visited.Add(original, copiedArray);

            for (int i = 0; i < copiedArray.Length; i++)
            {
                copiedArray.SetValue(CopyRecursive(originalArray.GetValue(i), visited),i);
            }
            return copiedArray;
        }

        // 创建对象实例(支持无构造函数类型)
        object copy = FormatterServices.GetUninitializedObject(type);
        visited.Add(original, copy);

        // 复制所有字段
        foreach (FieldInfo field in type.GetFields(BindingFlags.Public |
                                                BindingFlags.NonPublic |
                                                BindingFlags.Instance))
        {
            object fieldValue = field.GetValue(original);
            field.SetValue(copy, CopyRecursive(fieldValue, visited));
        }

        return copy;
    }
}

    // 使用示例
    class Program
    {
        static void Main(string[] args)
        {
            var original = new Person
            {
                Name = "Alice",
                Address = new Address { Street = "123 Main St" },
                MyArray=new int[2] {1,2}
            };

            // 方法一测试
            var copy1 = DeepCopyHelper.DeepCopyUsingSerialization(original);
            copy1.Name = "Bob";
            copy1.Address.Street = "456 Elm St";
            copy1.MyArray = new int[3] { 1, 2, 3 };
            Console.WriteLine("序列化方法:");
            Console.WriteLine("Original: " + original);
            Console.WriteLine("Copy:     " + copy1);

            // 方法二测试
            var copy2 = DeepCopyHelper.DeepCopyUsingJson(original);
            copy2.Name = "Charlie";
            copy2.Address.Street = "789 Oak St";
            copy2.MyArray = new int[3] { 1, 2, 3 };
            Console.WriteLine("\nJSON方法:");
            Console.WriteLine("Original: " + original);
            Console.WriteLine("Copy:     " + copy2);

            // 方法三测试
            var copy3 = DeepCopyHelper.DeepCopyUsingReflection(original);
            copy3.Name = "David";
            copy3.Address.Street = "101 Pine St";
            copy3.MyArray = new int[3] { 1, 2, 3 };
            Console.WriteLine("\n反射方法:");
            Console.WriteLine("Original: " + original);
            Console.WriteLine("Copy:     " + copy3);
            Console.ReadKey();
        }
    }
三种方法加测试

 

posted @ 2025-03-11 11:17  apple-hu  阅读(22)  评论(0)    收藏  举报