C# 从超类型克隆
C# clone from supertype
抽象超类型 Animal 有许多子类型,Cat、Dog 等。这些子类型只有一个构造函数和 Animal 中发现的虚拟方法的重写 - 即它们没有自己独有的属性或方法。 Class Zoo 有很多关于动物的参考和列表,但不知道或永远不需要知道猫、狗等。启用 Zoo 深度复制的最佳方法是什么? ,最好在 Cat、Dog 等中很少或没有新代码
如果您担心需要创建一个新的 Clone
实现,只是为了获得正确的类型(因为基 class 中 this
的类型是一个移动目标),您可以使用 Activator.CreateInstance
为覆盖 Animal
:
的所有类型创建当前类型的新实例
var copy = (Animal)Activator.CreateInstance(this.GetType());
copy.HasClaws = this.HasClaws; // copy Animal properties
您需要一个无参数的构造函数才能使此 Activator.CreateInstance
调用有效。
深度克隆对象的一种快速简便的方法是将其序列化为 MemoryStream
,然后将其反序列化回对象图。反序列化的副本将是一个没有引用原始对象的深度克隆图。与手动克隆对象相比,它可能需要更多的内存和 CPU 密集型,但编码工作要少得多;最终结果通常是可以接受的。
这是从 CodeProject:
中获取的一种实现
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
/// <span class="code-SummaryComment"><summary></span>
/// Provides a method for performing a deep copy of an object.
/// Binary Serialization is used to perform the copy.
/// <span class="code-SummaryComment"></summary></span>
public static class ObjectCopier
{
/// <span class="code-SummaryComment"><summary></span>
/// Perform a deep Copy of the object.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><typeparam name="T">The type of object being copied.</typeparam></span>
/// <span class="code-SummaryComment"><param name="source">The object instance to copy.</param></span>
/// <span class="code-SummaryComment"><returns>The copied object.</returns></span>
public static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
可以这样调用:
ObjectCopier.Clone(objectBeingCloned);
抽象超类型 Animal 有许多子类型,Cat、Dog 等。这些子类型只有一个构造函数和 Animal 中发现的虚拟方法的重写 - 即它们没有自己独有的属性或方法。 Class Zoo 有很多关于动物的参考和列表,但不知道或永远不需要知道猫、狗等。启用 Zoo 深度复制的最佳方法是什么? ,最好在 Cat、Dog 等中很少或没有新代码
如果您担心需要创建一个新的 Clone
实现,只是为了获得正确的类型(因为基 class 中 this
的类型是一个移动目标),您可以使用 Activator.CreateInstance
为覆盖 Animal
:
var copy = (Animal)Activator.CreateInstance(this.GetType());
copy.HasClaws = this.HasClaws; // copy Animal properties
您需要一个无参数的构造函数才能使此 Activator.CreateInstance
调用有效。
深度克隆对象的一种快速简便的方法是将其序列化为 MemoryStream
,然后将其反序列化回对象图。反序列化的副本将是一个没有引用原始对象的深度克隆图。与手动克隆对象相比,它可能需要更多的内存和 CPU 密集型,但编码工作要少得多;最终结果通常是可以接受的。
这是从 CodeProject:
中获取的一种实现using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
/// <span class="code-SummaryComment"><summary></span>
/// Provides a method for performing a deep copy of an object.
/// Binary Serialization is used to perform the copy.
/// <span class="code-SummaryComment"></summary></span>
public static class ObjectCopier
{
/// <span class="code-SummaryComment"><summary></span>
/// Perform a deep Copy of the object.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><typeparam name="T">The type of object being copied.</typeparam></span>
/// <span class="code-SummaryComment"><param name="source">The object instance to copy.</param></span>
/// <span class="code-SummaryComment"><returns>The copied object.</returns></span>
public static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
可以这样调用:
ObjectCopier.Clone(objectBeingCloned);