可修复的接口



这与"Watson et al: Beginning Visual C# Chapter 10: 练习 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;
    }

在 Person 类中,我们有:

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

要在程序.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);
        }

这有效,并保留了"米克"的原始值。但问题是首先在人和人类上实现":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;
     }
 }           

我悲惨地试图让这个递归工作,但我们最终得到的只是一个 StackOverflow。除了使用全局/静态变量退出循环之外,是否存在一种优雅的方法来"递归"地实现这种方式?

  clonedCloner.MyContent = MyContent.Clone();

内容类不实现 ICloneable,因此此语句无法编译。 你有点迷茫,我看不出你实际使用了哪个克隆实现,以及这个类与 Person 有什么关系。

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

坦率地说,这本书并没有教你很好的实践。 ICloneable 接口勉强逃脱了弃用,应避免使用。 这是一个损坏的接口,它不允许调用方指定是否需要深层副本或浅副本。 很多时候,它被实现为一个浅拷贝,因为它既便宜又容易,而调用者真的想要一个深拷贝。 产生一个很难诊断的讨厌的错误。

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

不要纠缠于此,继续阅读本书。 一定要考虑找一个更好的。

/* Here is a simple program of Deep copy. This will help you to fully understand ICloneable Interface.
using System;
namespace ICloneableDemo
{
    class Program
    {
        class Demo : ICloneable
        {
            public int a, b;
            public Demo(int x, int y)
            {
                a = x;
                b = y;
            }
            public override string ToString()
            {
                return string.Format(" a : " + a + "  b: " + b);
            }

            public object Clone()
            {
                Demo d = new Demo(a, b);
                return d;
            }
        }

        static void Main(string[] args)
        {
            Demo d1 = new Demo(10, 20);
            Console.WriteLine(" d1 : "+d1);
            Demo d2 = (Demo)d1.Clone();
            Console.WriteLine(" d2 : " + d2);
            Demo d3 = (Demo)d2.Clone();
            Console.WriteLine(" d3 : " + d3);
            Console.WriteLine("Changing the value of d1");
            d1.a = 44; 
            d1.b = 33;

            Console.WriteLine(" d1 : " + d1);
            Console.WriteLine(" d2 : " + d2);
            Console.WriteLine(" d3 : " + d3);

            Console.WriteLine("Changing the value of d3");
            d3.a = 50;
            d3.b = 60;
            Console.WriteLine(" d1 : " + d1);
            Console.WriteLine(" d2 : " + d2);
            Console.WriteLine(" d3 : " + d3);

            Console.ReadKey();
        }
    }
}
/*Output:
 d1 :  a : 10  b: 20
 d2 :  a : 10  b: 20
 d3 :  a : 10  b: 20
Changing the value of d1
 d1 :  a : 44  b: 33
 d2 :  a : 10  b: 20
 d3 :  a : 10  b: 20
Changing the value of d3
 d1 :  a : 44  b: 33
 d2 :  a : 10  b: 20
 d3 :  a : 50  b: 60
*/

/* 注意输出,当一个对象的值被更改时,它不会影响别人。因此,当一个对象被克隆时,它的行为就像一个单独的对象 */

相关内容

  • 没有找到相关文章

最新更新