c#中的对象克隆

本文关键字:对象 | 更新日期: 2023-09-27 18:27:53

考虑一下这个相关的问题:深度克隆对象

这真的是克隆对象的最佳方式吗?(序列化/反序列化)。序列化对我来说似乎有点贵。

我的想法是创建第二个构造函数,只分配所有变量。这种方法会更快吗?

class Test
{
public Test(Test clone)
{
// clone ....
}
}

c#中的对象克隆

这取决于您想要克隆什么以及为什么要克隆。如果浅层克隆是可以的,那么:

private static T CloneShallow<T>(T i) {
    return
        (T)i.GetType()
            .GetMethod(
                "MemberwiseClone",
                BindingFlags.Instance | BindingFlags.NonPublic
            ).Invoke(i, null);
}

这是克隆任何类型的简单记录的最快方法。

如果你需要完整的副本,但不是时间关键,那么:

private static T CloneFull<T>(T i) {
    if (Object.ReferenceEquals(i, null)) return default(T);
    var x = new XmlSerializer(i.GetType());
    using (var m = new MemoryStream()) {
        x.Serialize(m, i);
        m.Seek(0, SeekOrigin.Begin);
        return (T)x.Deserialize(m);
    }
}

第二个比第一个慢大约70倍。

如果您需要完整复制,并且速度很重要,可以考虑使用protobuf-net作为序列化程序。

有很多答案涉及修改你想要克隆的对象,但通常你只需要克隆一个简单的记录,而不想在它上实现任何东西

如果你想知道CloneFull()的速度有多慢——在我的电脑上(i5 661@3.33GHz),用一个非常简单的记录,它花了360次滴答声,给出了36ns。这在大多数情况下足够快:)

关键短语在接受答案中

这样做的好处是,当对象变得过于复杂时,您不必担心克隆所有内容。

串行化方法适用于任何复杂的对象。虽然对于更小、更简单的对象来说,这可能有些过头了,但它是一个可扩展的解决方案。

如果你知道你的对象不会改变,并且你只想克隆简单的对象,那么你的方法是完全可以接受的。尽管实现ICloneable接口是首选解决方案。

您所指的问题涉及适用于任何支持序列化的通用克隆。如果只想为您的特定对象进行克隆,只需实现ICloneable即可。

class Test : ICloneable {
    public object Clone() {
        // clone ....
    }
}

如果您正在讨论使用自定义类,最好的方法是实现ICloneable。通过这种方式,您的类可以提供一种标准化的方法来克隆自己。

有时,使用"复制构造函数"可能会更好,但通常只有当您看到它很简单,并且ICloneable不能充分满足您的需求时。

ICloneable

报价:

支持克隆,它创建一个与现有实例具有相同值的类的新实例。ICloneable接口包含一个成员Clone,用于支持MemberwiseClone提供的克隆之外的克隆。有关克隆、深层副本与浅层副本以及示例的详细信息,请参见Object.MemberwiseClone方法。

序列化仅适用于,对于存储以后/其他地方要检索的对象的表示形式特别有用。如果您希望对象能够克隆,那么您应该实现一个ICloneable接口。