从超类型C#克隆

时间:2015-04-10 12:48:37

标签: c# .net clone

抽象超类型Animal有许多子类型,Cat,Dog等。这些子类型只有一个构造函数和动物中的虚拟方法的覆盖 - 即它们没有自己独有的属性或方法。 Class Zoo有许多引用和动物列表,但不知道或者将不需要了解Cats,Dogs等。启用动态深度复制的最佳方法是什么? ,最好在Cat,Dog等中很少或没有新代码。

2 个答案:

答案 0 :(得分:3)

如果您担心需要创建新的Clone实现,只是为了获得正确的类型(因为基类中this的类型是移动目标),您可以使用Activator.CreateInstance为覆盖Animal的所有类型创建当前类型的新实例:

var copy = (Animal)Activator.CreateInstance(this.GetType());

copy.HasClaws = this.HasClaws; // copy Animal properties

您需要一个无参数构造函数才能使此Activator.CreateInstance调用工作。

答案 1 :(得分:1)

深度克隆对象的一种快捷方法是将其序列化为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);