提问人:underloaded_operator 提问时间:10/17/2023 更新时间:10/17/2023 访问量:92
如何在没有序列化的情况下在 C# 中创建真正的深度副本?
How to Create True Deep Copies in C# Without Serialization?
问:
我正在阅读《丁格尔,A.》(2021 年)一书。章节:在 C# 中克隆。在《面向对象的设计选择》(第 71-73 页)中,CRC Press“,在有关 C# 中的克隆的章节中,它展示了如何通过类制作对象的深度和浅层副本。UCopy
我很难理解这一切是如何运作的。我在网上找到了一些博客,它说很难在 C# 中制作真正的深度副本(没有 Serialize 和 Deserialize 方法)。我正在努力在我的作业中实现这一点,我无法围绕这个过程。
- 我制作的每个类都需要一个类吗(是只复制一个类,还是应该是通用的)
UCopy
- 它是否创建了真正的深层副本?我可能是错的,但据我所知,这不是一个真正的深层拷贝,因为,就像 中一样,AnotherClass 对象是不同的,但值并不是真正不同的,因为它是从同一个 初始化的。
u4
u3
Own
static id
- 该方法从何而来?
Clone
这是书中的代码示例(图 3.5)
public class AnotherClass
{
private static uint id = 1000;
private readonly uint own;
public AnotherClass()
{
own = id++;
}
public uint Own => own;
}
public class UCopy
{
private AnotherClass address;
public UCopy()
{
address = new AnotherClass();
}
// Deep copy: heap memory allocated for a true copy
public UCopy DeepCopy()
{
// Internal cast
UCopy local = (UCopy)this.MemberwiseClone();
local.address = new AnotherClass();
return local;
}
// Shallow copy: distinct objects have the same address
public UCopy ShallowCopy()
{
return (UCopy)this.MemberwiseClone();
}
}
public class Program
{
public static void Main()
{
// Client code
// #1: UCopy object allocated
UCopy u1 = new UCopy();
// Embedded 'Own' id of 1000
// #2: Shallow copy, aliased with u1
UCopy u2 = u1.ShallowCopy();
// Embedded 'Own' id of 1000
// #3: Shallow copy, aliased with u1
UCopy u3 = u1.DeepCopy();
// Embedded 'Own' id of 1000
// #4: Deep copy - DISTINCT object
UCopy u4 = u1.DeepCopy();
// Embedded 'Own' id of 1001
}
}
答:
1赞
Enigmativity
10/17/2023
#1
如果使用,你会掉进一个很深的兔子洞,因为它真的不清楚你需要修改什么才能制作一个深度克隆。MemberwiseClone()
你最好编写我们自己的深度克隆方法并显式更新所有内容。
下面是一个示例:
public class Class1
{
public Class2 Class2 { get; init; }
public string Id { get; set; }
public Class1 DeepCopy() => new Class1()
{
Id = this.Id,
Class2 = this.Class2.DeepCopy()
};
}
public class Class2
{
public Class3 Class3 { get; init; }
public string Id { get; set; }
public Class2 DeepCopy() => new Class2()
{
Id = this.Id,
Class3 = this.Class3.DeepCopy()
};
}
public class Class3
{
public string Id { get; set; }
public Class3 DeepCopy() => new Class3()
{
Id = this.Id
};
}
不过,我认为您最好在每个类上编写静态方法来进行克隆:
public class Class1
{
public Class2 Class2 { get; init; }
public string Id { get; init; }
public static Class1 DeepClone(Class1 clone) => new Class1()
{
Id = clone.Id,
Class2 = Class2.DeepClone(clone.Class2)
};
}
public class Class2
{
public Class3 Class3 { get; init; }
public string Id { get; init; }
public static Class2 DeepClone(Class2 clone) => new Class2()
{
Id = clone.Id,
Class3 = Class3.DeepClone(clone.Class3)
};
}
public class Class3
{
public string Id { get; init; }
public static Class3 DeepClone(Class3 clone)
=> new Class3() { Id = clone.Id };
}
然后你会这样写:
Class1 object1 = new Class1()
{
Id = "C1",
Class2 = new Class2()
{
Id = "C2",
Class3 = new Class3()
{
Id = "C3",
}
}
};
Class1 object1c = Class1.DeepClone(object1);
无论哪种情况,您都可以 100% 控制深度克隆过程,并且您正在做什么是明确的。
评论
0赞
underloaded_operator
10/17/2023
谢谢!这绝对更有意义
评论