C# 可克隆接口
这与“Watson等人:开始Visual C第10章:练习4”有关: 在People类上实现iClonable接口,以提供深度复制功能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() {
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吗?反之亦然?该死,不。继续,几个月后它会有意义。