Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 可克隆接口_C#_Recursion_Icloneable - Fatal编程技术网

C# 可克隆接口

C# 可克隆接口,c#,recursion,icloneable,C#,Recursion,Icloneable,这与“Watson等人:开始Visual C第10章:练习4”有关: 在People类上实现iClonable接口,以提供深度复制功能 class People : DictionaryBase: ICloneable public void DictAdd(Person newPerson) { Dictionary.Add(newPerson.Name, newPerson); public object Clone() {

这与“Watson等人:开始Visual C第10章:练习4”有关: 在People类上实现iClonable接口,以提供深度复制功能

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;

    }
要在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);
        }
这部作品,保留了“米克”的原始价值。
但问题是首先要在人和人的阶级上实现: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;
     }
 }           
我们曾痛苦地尝试让这个递归工作,但我们最终得到的只是堆栈溢出。除了使用全局/静态变量退出循环外,是否存在一种优雅的方式来“递归”实现此功能

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

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

坦率地说,这本书并没有教你很好的做法。iClonable接口勉强避免被弃用,应该避免使用。它是一个断开的接口,不允许调用方指定是需要深度副本还是浅层副本。通常,它被实现为浅拷贝,因为它既便宜又简单,而调用方真正想要的是深拷贝。产生了一个很难诊断的讨厌的bug

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

不要沉湎于此,在书中继续前进。一定要找个更好的。< /P>
/* 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
*/
Content类未实现ICloneable,因此无法编译此语句。您有点迷路了,我看不出您实际使用了Cloner的哪个实现,以及这个类与Person有什么关系

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

坦率地说,这本书并没有教你很好的做法。iClonable接口勉强避免被弃用,应该避免使用。它是一个断开的接口,不允许调用方指定是需要深度副本还是浅层副本。通常,它被实现为浅拷贝,因为它既便宜又简单,而调用方真正想要的是深拷贝。产生了一个很难诊断的讨厌的bug

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

不要沉湎于此,在书中继续前进。一定要找个更好的。< /P>
/* 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
*/
/*注意输出,当一个对象的值更改时,它不会影响 其他的。因此,克隆对象时,其行为类似于单独的对象*/

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

“不管有没有它,代码都是一样的。”你的意思是,更具体一点。“没有它”的代码是什么样子的?另外,在第二个示例中,您有两个Cloner类,这是错误吗?抱歉,我的意思是:class People:DictionaryBase而不是class People:DictionaryBase:iClonable。另一个代码是经过编辑的,抱歉。“代码在有或没有它的情况下都是一样的。”您的意思是,更具体一点。“没有它”的代码是什么样子的?另外,在第二个示例中,您有两个Cloner类,这是错误吗?抱歉,我的意思是:class People:DictionaryBase而不是class People:DictionaryBase:iClonable其他代码已编辑,抱歉。~Hans:谢谢您的见解,“MyContent.Clone()”磨磨蹭蹭的小精灵:bined。然后首选的选项是从VS10“升级”以利用内置的“DeepClone”?此外,鉴于“new”操作符在内存中创建对象的深度副本,除了C语言规范中的D/Ling,是否有比MSDN更好的“new”操作符描述?维兹—(愚蠢的问题?)新的代码是否包括memberwiseclone,反之亦然?该死,不。请继续,几个月后它会有意义。~Hans:谢谢你的见解,磨磨蹭蹭的“MyContent.Clone()”小精灵:bined。然后首选的选项是从VS10“升级”以利用内置的“DeepClone”?同样,考虑到“new”操作符在内存中创建对象的深度副本,除了C语言规范中的D/L之外,还有比MSDN更好的“new”操作符描述吗?即—(愚蠢的问题?)“new”的代码包括memberwiseclone吗?反之亦然?该死,不。继续,几个月后它会有意义。