我想要一份真正的深度拷贝。在Java中,这很容易,但在c#中如何做到呢?
当前回答
基于Kilhoffer的解决方案……
在c# 3.0中,你可以像下面这样创建一个扩展方法:
public static class ExtensionMethods
{
// Deep clone
public static T DeepClone<T>(this T a)
{
using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, a);
stream.Position = 0;
return (T) formatter.Deserialize(stream);
}
}
}
用DeepClone方法扩展任何标记为[Serializable]的类
MyClass copy = obj.DeepClone();
其他回答
重要提示
BinaryFormatter已弃用,2023年11月后将不再在. net中使用。参见BinaryFormatter废弃策略
我已经看到了一些不同的方法,但我使用一个通用的实用方法:
public static T DeepClone<T>(this T obj)
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
return (T) formatter.Deserialize(ms);
}
}
注:
你的类必须被标记为[Serializable]才能工作。 您的源文件必须包括以下代码: 使用System.Runtime.Serialization.Formatters.Binary; 使用先;
你可以试试这个
public static object DeepCopy(object obj)
{
if (obj == null)
return null;
Type type = obj.GetType();
if (type.IsValueType || type == typeof(string))
{
return obj;
}
else 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(DeepCopy(array.GetValue(i)), i);
}
return Convert.ChangeType(copied, obj.GetType());
}
else if (type.IsClass)
{
object toret = Activator.CreateInstance(obj.GetType());
FieldInfo[] fields = type.GetFields(BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance);
foreach (FieldInfo field in fields)
{
object fieldValue = field.GetValue(obj);
if (fieldValue == null)
continue;
field.SetValue(toret, DeepCopy(fieldValue));
}
return toret;
}
else
throw new ArgumentException("Unknown type");
}
感谢解毒83关于代码项目的文章。
基于Kilhoffer的解决方案……
在c# 3.0中,你可以像下面这样创建一个扩展方法:
public static class ExtensionMethods
{
// Deep clone
public static T DeepClone<T>(this T a)
{
using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, a);
stream.Position = 0;
return (T) formatter.Deserialize(stream);
}
}
}
用DeepClone方法扩展任何标记为[Serializable]的类
MyClass copy = obj.DeepClone();
也许你只需要一个浅拷贝,在这种情况下使用Object.MemberWiseClone()。
在MemberWiseClone()的文档中有一些很好的深度复制策略建议:-
http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx
public static object CopyObject(object input)
{
if (input != null)
{
object result = Activator.CreateInstance(input.GetType());
foreach (FieldInfo field in input.GetType().GetFields(Consts.AppConsts.FullBindingList))
{
if (field.FieldType.GetInterface("IList", false) == null)
{
field.SetValue(result, field.GetValue(input));
}
else
{
IList listObject = (IList)field.GetValue(result);
if (listObject != null)
{
foreach (object item in ((IList)field.GetValue(input)))
{
listObject.Add(CopyObject(item));
}
}
}
}
return result;
}
else
{
return null;
}
}
这种方式比BinarySerialization快几倍,而且不需要[Serializable]属性。