zoukankan      html  css  js  c++  java
  • 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;
            }
        }
    复制代码
  • 相关阅读:
    C#利用HttpWebRequest进行post请求的示例(HTTPS)
    以文件流的方式读取本地文件
    C#读取xml文件指定节点下的值
    C# get post 的方法
    SQL2008安装后激活方式以及提示评估期已过解决方法(转)
    python 左移右移 2个数交换
    python 循环内部添加多个条件判断会出现越界
    python __new__ __init__ __del__
    python 模块中__all__作用
    Python urllib的urlretrieve()函数解析 (显示下载进度)
  • 原文地址:https://www.cnblogs.com/deepalley/p/14184060.html
Copyright © 2011-2022 走看看