c# 几种深拷贝方式的比较

 

 
复制代码
复制代码
    public static class Tools
    {
        //利用 BinaryFormatter 实现深拷贝
        public static T DeepCopyByBinary<T>(this T obj)
        {
            T t = default(T);
            IFormatter formatter = new BinaryFormatter();
            using (MemoryStream ms = new MemoryStream())
            {
                formatter.Serialize(ms, obj);
                ms.Seek(0, SeekOrigin.Begin);
                t = (T)formatter.Deserialize(ms);
            }
            return t;
        }

        //利用 XmlSerializer 实现深拷贝
        public static T DeepCopyByXml<T>(this T obj)
        {
            T t = default(T);
            XmlSerializer xmlserialize = new XmlSerializer(typeof(T));
            using (MemoryStream ms = new MemoryStream())
            {
                xmlserialize.Serialize(ms, obj);
                ms.Seek(0, SeekOrigin.Begin);
                t = (T)xmlserialize.Deserialize(ms);
            }
            return t;
        }

        //利用反射实现深拷贝
        public static T DeepCopyByReflection<T>(this T tSource)
        {
            T tResult = Activator.CreateInstance<T>();
            Type sourceType = typeof(T);
            Type resultType = typeof(T);
            var sourcePros = sourceType.GetProperties();
            foreach (var pro in sourcePros)
            {
                var sourceProValue = pro.GetValue(tSource);
                var resultPro = resultType.GetProperty(pro.Name);
                resultPro.SetValue(tResult, sourceProValue);
            }
            return tResult;
        }
    }
复制代码
复制代码

 

复制代码
复制代码
            Person p1 = new Person { Id = 1, Name = "wjire" };
            Stopwatch sw1 = new Stopwatch();
            sw1.Start();
            for (int i = 0; i < 100000; i++)
            {
                Person p2 = p1.DeepCopyByBinary();
            }
            sw1.Stop();
            Console.WriteLine($"DeepCopyByBinary 共耗时 {sw1.ElapsedMilliseconds} 毫秒");



            Stopwatch sw2 = new Stopwatch();
            sw2.Start();
            for (int i = 0; i < 100000; i++)
            {
                Person p2 = p1.DeepCopyByXml();
            }
            sw2.Stop();
            Console.WriteLine($"DeepCopyByXml 共耗时 {sw2.ElapsedMilliseconds} 毫秒");


            Stopwatch sw3 = new Stopwatch();
            sw3.Start();
            for (int i = 0; i < 100000; i++)
            {
                Person p2 = p1.DeepCopyByReflection();
            }
            sw3.Stop();
            Console.WriteLine($"DeepCopyByReflection 共耗时 {sw3.ElapsedMilliseconds} 毫秒");


            //利用 json.net 实现深拷贝
            Stopwatch sw4 = new Stopwatch();
            sw4.Start();
            for (int i = 0; i < 100000; i++)
            {
                Person p2 = JsonConvert.DeserializeObject<Person>(JsonConvert.SerializeObject(p1));
            }
            sw4.Stop();
            Console.WriteLine($"Newtonsoft.Json 共耗时 {sw4.ElapsedMilliseconds} 毫秒");
复制代码
复制代码

 

运行结果:

 

反射最快!!

 

 

 

 

复制代码
复制代码
    class Program
    {
        static void Main(string[] args)
        {
            Person p1 = new Person(123)
            {
                Id = 1,
                Age = 33,
                Name = "wjire"
            };

            Expression<Func<Person, Person>> exp1 = p => new Person(333) { Id = p.Id, Name = p.Name, Age = p.Age };
            var func1 = exp1.Compile();
            Person p23 = func1(p1);
            Console.WriteLine(p23.Id);



            Console.WriteLine("*****************************");
            ParameterExpression parameterExpression = Expression.Parameter(p1.GetType(), "p"); // 创造了 lambda表达式中的入参: p
            Console.WriteLine(parameterExpression);

            List<MemberBinding> memberBindingList = new List<MemberBinding>();
            foreach (PropertyInfo pro in p1.GetType().GetProperties())
            {
                if (!pro.CanWrite)
                {
                    continue;
                }
                MemberExpression property = Expression.Property(parameterExpression, pro.Name);
                Console.WriteLine(property);// p.Id,p.Name,p.Age

                MemberBinding memberBinding = Expression.Bind(pro, property);
                Console.WriteLine(memberBinding);// p=p.Id,p=p.Name,p=p.Age

                memberBindingList.Add(memberBinding);
            }

            var rr = Expression.New(p1.GetType().GetConstructor(new Type[] { typeof(int) }), Expression.Constant(default(int)));

            MemberInitExpression initExpression = Expression.MemberInit(rr, memberBindingList);
            Console.WriteLine(initExpression);// new Person { Id = p.Id, Name = p.Name, Age = p.Age }

            Expression<Func<Person, Person>> exp = Expression.Lambda<Func<Person, Person>>(initExpression, parameterExpression);
            Console.WriteLine(exp);// p => new Person { Id = p.Id, Name = p.Name, Age = p.Age }

            Func<Person, Person> func = exp.Compile();
            Person p2 = func(p1);

            Console.WriteLine(p2.Name);
            Console.WriteLine(p2.Id);
            Console.WriteLine(p2.Age);
            Console.ReadKey();
        }
    }

    internal class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public int Age { get; set; }


        public Person(int id)
        {
            this.Id = id;
        }
    }
复制代码
复制代码
posted @   八英里  阅读(335)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示