# 深拷贝 & 浅拷贝
  • 浅拷贝:指的是拷贝一个对象时,仅仅拷贝对象的引用进行拷贝,但是拷贝对象和源对象还是引用同一份实体。此时,其中一个对象的改变都会影响到另一个对象。
  • 深拷贝:指的是拷贝一个对象时,不仅仅把对象的引用进行复制,还把该对象引用的值也一起拷贝。这样进行深拷贝后的拷贝对象就和源对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。
# 补充

NET中值类型默认是深拷贝的,而对于引用类型,默认实现的是浅拷贝

# 深拷贝的几种方式
  1. 序列化
  2. 反射
  3. 表达式树 (表达式缓存)
# 序列化
# 三种方式:Xml、二进制、数据契约 DataContractSerializer
  • 利用 XML 序列化和反序列化实现
/// <summary>
/// 利用 XML 序列化和反序列化实现
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
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;
}
  • 利用二进制序列化和反序列实现
/// <summary>
/// 利用二进制序列化和反序列实现
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static T DeepCopyWithBinarySerialize<T>(T obj)
{
    using MemoryStream stream = new MemoryStream();
    IFormatter formatter = new BinaryFormatter();
    formatter.Serialize(stream, obj);
    // 将当前流的位置设置成起始位置
    stream.Seek(0, SeekOrigin.Begin);
    return (T)formatter.Deserialize(stream);
}
  • 利用 DataContractSerializer 序列化和反序列化实现
/// <summary>
/// 利用 DataContractSerializer 序列化和反序列化实现
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static T DeepCopy<T>(T obj)
{
    object retval;
    using (MemoryStream ms = new MemoryStream())
    {
        DataContractSerializer ser = new DataContractSerializer(typeof(T));
        ser.WriteObject(ms, obj);
        ms.Seek(0, SeekOrigin.Begin);
        retval = ser.ReadObject(ms);
        ms.Close();
    }
    return (T)retval;
}
# 反射
/// <summary>
/// 反射的方式拷贝
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static T ReflreshClone<T>(T obj)
{
    Type type = obj.GetType();
    // 对于值类型和 string 的特性(驻留性) .Net 值类型默认是深拷贝
    if (obj is string || type.IsValueType) return obj;
    // 如果是数组类型
    if (type.IsArray)
    {
        Type elementType = Type.GetType(type.FullName.Replace("[]", string.Empty));
        //Type elementType = type.GetElementType();
        var array = obj as Array;
        Array copied = Array.CreateInstance(elementType, array.Length);
        for (int i = 0; i < array.Length; i++)
        {
            copied.SetValue(ReflreshClone(array.GetValue(i)), i);
        }
        return (T)Convert.ChangeType(copied, obj.GetType());
    }
    T newObj = (T)Activator.CreateInstance(type);
    foreach (PropertyInfo prop in type.GetProperties(
        BindingFlags.Public | BindingFlags.NonPublic 
        | BindingFlags.Instance | BindingFlags.Static))
    {
        // 判断属性是否可写 get set 访问器
        if (prop.CanWrite)
        {
            var prototypeValue = prop.GetValue(obj, null);
            if (prototypeValue == null)
            {
                continue;
            }
            prop.SetValue(newObj, prototypeValue);
        }
    }
    return newObj;
}
# 表达式缓存克隆
public static class CloneExpression<T, R>
{
    private static readonly Func<T, R> cache = GetFunc();
    private static Func<T, R> GetFunc()
    {
        // 创建表达式树种的参数或变量的节点 p=>
        ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "p");
        // 存放参数或者变量
        List<MemberBinding> memberBindingList = new List<MemberBinding>();
        // 构造 p=> new R {a=p.a,b=p.b,c=0};
        foreach (var item in typeof(R).GetProperties())
        {
            if (!item.CanWrite)
                continue;
            PropertyInfo info = typeof(T).GetProperty(item.Name);
            if(info != null)
            {
                // 创建属性 p.a p.b p.c
                MemberExpression property = Expression.Property(parameterExpression, info);
                // 字段与属性绑定 a = p.a
                MemberBinding memberBinding = Expression.Bind(item, property);
                memberBindingList.Add(memberBinding);
            }
        }
        //new B() {a = p.a, b = p.b}
        MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(R)), memberBindingList.ToArray());
        //p => new B() {a = p.a, b = p.b}
        Expression<Func<T, R>> lambda = Expression.Lambda<Func<T, R>>(memberInitExpression, new ParameterExpression[] { parameterExpression });
        return lambda.Compile();
    }
    public static R Clone(T T)
    {
        return cache(T);
    }
}
# 参考链接

Clone