從上面運行結果可以看出,.NET中值類型默認是深拷貝的,而對于引用類型,默認實現的是淺拷貝。所以對于類中引用類型的屬性改變時,其另一個對象也會發生改變。
上面已經介紹了淺拷貝的實現方式,那深拷貝要如何實現呢?在前言部分已經介紹了,實現深拷貝的方式有:反射、反序列化和表達式樹。在這里,我只介紹反射和反序列化的方式,對于表達式樹的方式在網上也沒有找到,當時面試官說是可以的,如果大家找到了表達式樹的實現方式,麻煩還請留言告知下。下面我們首先來看看反射的實現方式吧:
// 利用反射實現深拷貝
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;
}
反序列化的實現方式,反序列化的方式也可以細分為3種,具體的實現如下所示:
// 利用XML序列化和反序列化實現
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;
}
// 利用二進制序列化和反序列實現
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;
}
// 利用DataContractSerializer序列化和反序列化實現
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;
}
// 表達式樹實現
// 。。。。
評論
查看更多