首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ICloneable接口

ICloneable接口
EN

Stack Overflow用户
提问于 2014-04-06 05:12:27
回答 2查看 3.1K关注 0票数 1

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

代码语言:javascript
复制
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课程中:

代码语言:javascript
复制
        public object Clone()
    {
        Person newPerson = new Person();
        newPerson = (Person)newPerson.MemberwiseClone();
        newPerson.Age = age;
        newPerson.Name = name;
        return newPerson;

    }

要在Program.cs中测试它:

代码语言:javascript
复制
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的“递归”实现在其示例中的有效性。

代码语言:javascript
复制
 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。除了使用全局/静态变量退出循环之外,是否有一种优雅的方法可以“递归地”实现这一功能?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-06 07:17:19

代码语言:javascript
复制
  clonedCloner.MyContent = MyContent.Clone();

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

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

坦白地说,这本书并没有教你很好的实践。ICloneable接口差一点就被废弃了,应该避免。它是一个中断的接口,它不允许调用方指定需要一个深拷贝还是浅拷贝。通常情况下,它是作为一个浅拷贝实现的,因为它既便宜又简单,而调用方确实想要一个深拷贝。产生一个很难诊断的讨厌的错误。

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

不要纠缠于此,在书中继续前进。一定要考虑找一个更好的。

票数 4
EN

Stack Overflow用户

发布于 2017-11-11 20:28:56

代码语言:javascript
复制
/* 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
*/

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22890245

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档