【问题标题】:C# clone from supertypeC# 从超类型克隆
【发布时间】:2015-06-16 04:48:28
【问题描述】:

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

【问题讨论】:

  • 您可以将它们序列化到内存中,然后再次反序列化。这使得深拷贝。需要示例吗?

标签: c# .net clone


【解决方案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);

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 如果我有二十多个属性并且不想显式复制每个属性,我该怎么办?有没有办法在 .NET Core 中隐式执行此操作?
    猜你喜欢
    • 1970-01-01
    • 2015-03-27
    • 2015-05-01
    • 2011-01-19
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    相关资源
    最近更新 更多