我有一个名为“SmallClass”的C#类。
我有一个包含“SmallClass”类型对象的现有列表myList
我想要深度克隆列表“myList”。也就是说,深入克隆包含列表并深度克隆列表中包含的对象。
我该怎么做。
public class SmallClass: ICloneable {
public string str1;
public string str2;
public string str3;
public SmallClass Clone() //This just deep clones 1 object of type "SmallClass"
{
MemoryStream m = new MemoryStream();
BinaryFormatter b = new BinaryFormatter();
b.Serialize(m, this);
m.Position = 0;
return (SRO)b.Deserialize(m);
}
public override equals(Object a)
{
return Object.Equals(this.str1 && a.str1);
}
}
public class AnotherClass
{
SomeCode();
List<SmallClass> myList = new List<SmallList>(); //myList is initialized.
// NOW I want to deep clone myList. deep Clone the containing list and deep clone the objects contained in the list.
List<SmallClass> newList = new List<SmallClass>();
foreach(var item in myList)
{
newList.Add((SmallClass)item.Clone());
}
}
答案 0 :(得分:4)
您的SmallClass需要实现ICloneable接口。然后使用Clone()方法复制每个元素。
List<SmallClass> newList = new List<SmallClass>();
foreach(var item in myList)
{
newList.Add((SmallClass)item.Clone());
}
答案 1 :(得分:4)
首先,您可以定义用于深度克隆任何对象(根)的实用程序方法:
public static T DeepClone<T>(T obj)
{
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
stream.Position = 0;
return (T)formatter.Deserialize(stream);
}
}
如果您想深度克隆myList
,您只需将其作为参数传递给上述方法:
List<SmallClass> myListClone = DeepClone(myList);
您需要注意的最重要的考虑因素是,您的所有课程必须标记为可序列化,通常是[SerializableAttribute]
。
[SerializableAttribute]
public class SmallClass
{
// …
}
答案 2 :(得分:0)
有几种方法可以创建包含序列化和使用Object.MemberwiseClone Method()的深层副本。由于这里已经提供了使用序列化的示例,我有一种方法是使用“MemberwiseClone”。
注意:递归,平台:.NETStandard2.0
/// <summary>
/// Returns a deep copy of an object.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <returns></returns>
public static T DeepClone<T>(this T source) where T : class
{
if(source == null) return null;
if(source is ICollection<object> col)
{
return (T)DeepCloneCollection(col);
}
else if(source is IDictionary dict)
{
return (T)DeepCloneDictionary(dict);
}
MethodInfo method = typeof(object).GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance);
T clone = (T)method.Invoke(source, null);
foreach(FieldInfo field in source.GetType().GetRuntimeFields())
{
if(field.IsStatic) continue;
if(field.FieldType.GetTypeInfo().IsPrimitive) continue;
object sourceValue = field.GetValue(source);
field.SetValue(clone, DeepClone(sourceValue));
}
return clone;
}
private static ICollection<object> DeepCloneCollection(ICollection<object> col)
{
object[] arry = (object[])Activator.CreateInstance(col.GetType(), new object[] { col.Count });
for(int i = 0; i < col.Count; i++)
{
object orig = col.ElementAt(i);
object cln = DeepClone(orig);
arry[i] = cln;
}
return arry;
}
private static IDictionary DeepCloneDictionary(IDictionary dict)
{
IDictionary clone = (IDictionary)Activator.CreateInstance(dict.GetType());
foreach(object pair in dict)
{
object key = pair.GetValueOf("Key");
object original = pair.GetValueOf("Value");
clone.Add(key, original.DeepClone());
}
return clone;
}
public static dynamic GetValueOf<T>(this T value, string property)
{
PropertyInfo p = value.GetType().GetTypeInfo().GetProperty(property);
if(p != null && p.CanRead)
{
dynamic val = p.GetValue(value);
return val;
}
return Activator.CreateInstance(p.PropertyType); //Property does not have value, return default
}