【问题标题】:How to deep clone interconnected objects in C#?如何在 C# 中深度克隆互连对象?
【发布时间】:2010-10-15 13:38:46
【问题描述】:

深层克隆一组相互关联的对象的最佳方法是什么?示例:

class A {
    B theB; // optional
    // ...
}

class B {
    A theA; // optional
    // ...
}

class Container {
    A[] a;
    B[] b;
}

显而易见的事情是遍历对象并在我遇到它时深度克隆所有内容。然而,这会产生一个问题——如果我克隆一个包含BA,并且B 也在Container 中,那么在我克隆Container 之后,B 将被克隆两次。

下一个合乎逻辑的步骤是创建一个Dictionary 并在我克隆它之前查找每个对象。然而,这似乎是一个缓慢且不优雅的解决方案。

有什么想法吗?

【问题讨论】:

标签: c# clone


【解决方案1】:

这肯定不是一个优雅的解决方案,但使用字典(或哈希图)并不少见。好处之一是 hashmap 具有恒定的查找时间,因此这里的速度并没有真正受到影响。

【讨论】:

    【解决方案2】:

    我不熟悉 C#,但通常任何类型的图表抓取以进行某种处理都需要查找表来停止处理由于循环引用而导致的对象。所以我认为你需要在这里做同样的事情。

    【讨论】:

      【解决方案3】:

      您建议的字典解决方案是我所知道的最好的。为了进一步优化,您可以使用object.GetHashCode() 来获取对象的哈希值,并将其用作字典键。除非您在谈论巨大的对象树(数千个对象的 10 到 100 多个),否则应该很快。

      【讨论】:

        【解决方案4】:

        可能会创建一个位标志来指示此对象之前是否已被克隆。

        【讨论】:

          【解决方案5】:

          您可以研究的另一种可能的解决方案是将对象序列化为流,然后将它们从同一流中重构为新实例。当其他一切看起来非常复杂和混乱时,这通常会产生奇迹。

          马克

          【讨论】:

          • 您能详细说明一下吗?我怎样才能防止序列化同一个对象两次?或者,如果我只是序列化“容器”,如何将 references 存储到 A 和 B 而不是整个对象,以避免重复?我不能像您在简单示例中所相信的那样只使用简单的索引。
          • WCF 通过一些调整来支持这一点 (blogs.msdn.com/sowmy/archive/2006/03/26/561188.aspx)。但是序列化虽然可以快速编码,但其性能将比显式深拷贝差得多。
          • True - 再次序列化和反序列化在性能方面可能不是最好的。这归结为永恒的“取决于”场景:-)您是否需要顶级性能,并且您是否需要在循环中执行数十万次->那么序列化可能不是最佳选择。
          【解决方案6】:

          进行深度克隆的一种实用方法是对源图进行序列化然后反序列化。 .NET 中的一些序列化程序(例如 DataContractSerializer)甚至是 capable of processing cycles within graphs。您可以通过查看the feature comparison chart 来选择最适合您的场景的序列化程序。

          【讨论】:

            猜你喜欢
            • 2010-09-09
            • 1970-01-01
            • 2019-08-09
            • 1970-01-01
            • 2012-06-05
            • 2012-02-26
            • 2016-12-20
            相关资源
            最近更新 更多