ICloneable接口

Lau*_*arn 1 c# recursion icloneable

这涉及到《Watson et al: Beginning Visual C# Chapter 10:exercise 4》:在 People 类上实现 ICloneable 接口以提供深度复制功能

class People : DictionaryBase: ICloneable

    public void DictAdd(Person newPerson)
    {
        Dictionary.Add(newPerson.Name, newPerson);

    public object Clone()
    {

        People newPeople = new People();


        foreach (Person myPerson in Dictionary.Values)
        {
            Person ClonePerson = (Person)myPerson.Clone();
            newPeople.DictAdd(ClonePerson);
        }

        return newPeople;
    }
Run Code Online (Sandbox Code Playgroud)

在 Person 类中,我们有:

        public object Clone()
    {
        Person newPerson = new Person();
        newPerson = (Person)newPerson.MemberwiseClone();
        newPerson.Age = age;
        newPerson.Name = name;
        return newPerson;

    }
Run Code Online (Sandbox Code Playgroud)

要在 Program.cs 中测试它:

People clonedPeople = (People)PeopleCollection.Clone();

        PeopleCollection.Remove("Mick");
        myPerson1.Name = "Jock";
        myPerson1.Age = 13;
        PeopleCollection.DictAdd(myPerson1);


        Console.WriteLine("In the current collection \"Mick\" is now: \"{0}\" and his age is: {1}", myPerson1.Name, myPerson1.Age);
        Console.WriteLine("But \"Mick\" should remain in the original collection, now cloned.");
        foreach (DictionaryEntry p in clonedPeople)
        {
            Console.WriteLine();
            Console.WriteLine("myPerson Name: {0} myPerson.Age: {1}", ((Person)p.Value).Name, ((Person)p.Value).Age);
        }
Run Code Online (Sandbox Code Playgroud)

这有效,并且保留了“Mick”的原始值。但问题是首先要在 Person 和 People 类上实现“:ICloneable”。不管有没有它,代码的工作原理都是一样的。

一个相关的问题是他们所谓的在示例中运行 ICloneable 的“递归”实现的功效

 public class Content
 {
 public int Val;
 }
 public class Cloner: ICloneable
 {
 public Content MyContent = new Content();
 public Cloner(int newVal)
 {
 MyContent.Val = newVal;
 }
     public object Clone()
     {
     Cloner clonedCloner = new Cloner(MyContent.Val);
     return clonedCloner;
     }
 }           
Run Code Online (Sandbox Code Playgroud)

我们曾痛苦地尝试过让这个递归起作用,但最终我们得到的只是一个 StackOverflow。除了使用全局/静态变量来退出循环之外,是否存在一种优雅的方法来“递归”实现此循环?

Han*_*ant 5

  clonedCloner.MyContent = MyContent.Clone();
Run Code Online (Sandbox Code Playgroud)

Content 类未实现 ICloneable,因此该语句无法编译。你有点迷失了,我看不到你实际使用的 Cloner 的实现以及这个类与 Person有什么关系。

请注意,您实际上并没有测试是否获得了深度克隆。您仅通过检查集合是否未被修改来测试浅克隆情况。例如,深度克隆测试会改变米克的属性,并检查原始集合是否仍然有未修改的米克。这才是真正的“深”的意义。这在您的代码中是可以的,但是您会失去使用 MemberwiseClone() 的优雅点,它不会做任何有用的事情,并且与深度克隆相反。

坦率地说,这本书并没有教给你很好的实践。ICloneable 接口险些被弃用,应该避免。这是一个损坏的接口,它不允许调用者指定是否需要深拷贝或浅拷贝。很多时候,它被实现为浅拷贝,因为它便宜且简单,而调用者确实想要一个深拷贝。产生一个很难诊断的令人讨厌的错误。

如果您想支持深度克隆,只需Person DeepClone()向您的类添加一个方法即可。现在它是显式的且类型安全的。

别再纠结这个了,继续看书吧。请考虑寻找一个更好的。