c# 深拷贝浅拷贝

浅拷贝:仅仅把对象的引用进行拷贝,但是拷贝对象和源对象是引用同一份实体。此时,其中的一个的成员对象的改变都会影响到另外一个成员的对象

深拷贝:指的是拷贝一个对象时,不仅仅把对象的引用进行拷贝,还把该对象引用的值也一起拷贝。这样进行拷贝后的副本对象就和源对象互相独立,其中任何一个的成员对象改动都不会对两外一个成员对象造成影响

C#实现浅拷贝:调用MemberwiseClone方法,创建一个新的对象,然后复制当前对象的非静态字段的新对象创建一个浅副本。

C# 深拷贝的有三种实现:

1.反射

2.序列化

3.表达式树

浅拷贝的实现

using System;
using static _12深拷贝浅拷贝.DeepCopyClass;

namespace _12深拷贝浅拷贝
{
    internal class Program
    {
        static void Main(string[] args)
        {
            DeepCopyClass deepCopyClassA = new DeepCopyClass();
            deepCopyClassA.Id = 10;
            deepCopyClassA.demoEnum = DemoEnum.EnumA;
            deepCopyClassA.adress = new Address() { City = "Shanghai" };
            deepCopyClassA.Name = "DeepCopyClassDemo1";
            deepCopyClassA.IntArray = new int[] { 1, 2 };
            deepCopyClassA.testB = new TestB() { Property1 = 111 };


            //浅拷贝
            DeepCopyClass deepCopyClassB = deepCopyClassA.Clone() as DeepCopyClass;
            deepCopyClassB.Id = 1;
            deepCopyClassA.Name = "DeepCopyClassDemo1BBBBBB";
            deepCopyClassB.demoEnum = DemoEnum.EnumB;
            // 对于引用类型,对象和副本对象引用同一个内存地址,
            // 当在对象或者副本对象修改引用成员,引用类型的成员都会发生变化。
            deepCopyClassB.IntArray[0] = 3;
            deepCopyClassB.testB.Property1 = 222;

            Console.Write("A==B ? ");
            Console.WriteLine(deepCopyClassA == deepCopyClassB);

            //输出A和B对象
            Console.WriteLine("----------------A--------------");
            deepCopyClassA.Display();
            Console.WriteLine("----------------B--------------");
            deepCopyClassB.Display();

            Console.ReadLine();
        }
    }
    public class DeepCopyClass : ICloneable
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int[] IntArray { get; set; }
        public Address adress { get; set; }
        public DemoEnum demoEnum { get; set; }

        public TestB testB { get; set; }

        //实现ICloneable接口的Clone方法
        public object Clone()
        {
            //调用Object的MemberwiseClone(),创建当前object的浅表副本
            return MemberwiseClone() as DeepCopyClass;
        }


        public void Display()
        {
            Console.WriteLine("id=" + Id);
            Console.WriteLine("Name=" + Name);
            for (int i = 0; i < IntArray.Length; i++)
            {
                Console.WriteLine(string.Format("IntArray[{0}] = {1}", i, IntArray[i]));
            }
            Console.WriteLine("Address.City = " + adress.City);
            Console.WriteLine("DemoEnum = " + demoEnum);
            Console.WriteLine("TestB.Property1 = " + testB.Property1);
        }
        public class TestB
        {
            public int Property1 { get; set; }
        }
        /// <summary>
        /// 值类型
        /// </summary>
        public struct Address
        {
            public string City { get; set; }
        }

        public enum DemoEnum
        {
            EnumA = 0,
            EnumB = 1
        }
    }
}

深拷贝的实现:

一当要拷贝的类没有互相引用时

反射实现

 // 利用反射实现深拷贝
        #region MyRegion
        public static T DeepCopyWithReflection<T>(T obj)
        {
            Type type = obj.GetType();

            // 如果是字符串或值类型则直接返回
            if (obj is string || type.IsValueType) return obj;
            // 如果是数组
            if (type.IsArray)
            {
                Type elementType = Type.GetType(type.FullName.Replace("[]", string.Empty));
                var array = obj as Array;
                Array copied = Array.CreateInstance(elementType, array.Length);
                for (int i = 0; i < array.Length; i++)
                {
                    copied.SetValue(DeepCopyWithReflection(array.GetValue(i)), i);
                }
                return (T)Convert.ChangeType(copied, obj.GetType());
            }

            object retval = Activator.CreateInstance(obj.GetType());

            PropertyInfo[] properties = obj.GetType().GetProperties(
                BindingFlags.Public | BindingFlags.NonPublic
                | BindingFlags.Instance | BindingFlags.Static);
            foreach (var property in properties)
            {
                var propertyValue = property.GetValue(obj, null);
                if (propertyValue == null)
                    continue;
                property.SetValue(retval, DeepCopyWithReflection(propertyValue), null);
            }

            return (T)retval;
        }
        #endregion

序列化实现:

分为xml序列化和二进制序列化,json(没有C#内部实现,需要引用外部的包)等

// 利用XML序列化和反序列化实现
        #region MyRegion
        public static T DeepCopyWithXmlSerializer<T>(T obj)
        {
            object retval;
            using (MemoryStream ms = new MemoryStream())
            {
                XmlSerializer xml = new XmlSerializer(typeof(T));
                xml.Serialize(ms, obj);
                ms.Seek(0, SeekOrigin.Begin);
                retval = xml.Deserialize(ms);
                ms.Close();
            }

            return (T)retval;
        }
        #endregion

        // 利用二进制序列化和反序列实现
        #region MyRegion
        public static T DeepCopyWithBinarySerialize<T>(T obj)
        {
            object retval;
            using (MemoryStream ms = new MemoryStream())
            {
                BinaryFormatter bf = new BinaryFormatter();
                // 序列化成流
                bf.Serialize(ms, obj);
                ms.Seek(0, SeekOrigin.Begin);
                // 反序列化成对象
                retval = bf.Deserialize(ms);
                ms.Close();
            }

            return (T)retval;
        }
        #endregion

表达式树实现:

表达式可以时一个参数(如参数X),一个常数(如常树5),一个加运算(如x+5)等等,可以把几个小的表达式组装在一起成为大的表达式,例如:(x+5)-(++y).对于这样一个表达式可以用一棵树表示,如下:

 这就是表达式树,表达式树本身也是一个表达式(大的表达式)。一个表达式也是一颗表达式树,可以说它是一棵小的表达式树。可以把表达式树和表达式认为是一个东西,C#中都用Expression类表示

表达式树的创建

一Lambda表达式方法

表达式可以通过Lambda表示创建Expression<TDelegate>类型,如下:

Expression

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值