If your entire object graph is serialisable, my experience up to now is that deep cloning is much easier and maintainable using in-memory binary serialisation.
public static object DeepClone(object obj) { if (obj == null) return null; BinaryFormatter bf = new BinaryFormatter(); using (MemoryStream ms = new MemoryStream()) { bf.Serialize(ms, obj); ms.Position = 0; return bf.Deserialize(ms); } } Simple unit test: [Test()] public void DeepCloneTest() { Assert.IsNull(PC.Utilities.DeepClone(null)); DummyCloneable data = new DummyCloneable(); DummyCloneable clone = (DummyCloneable) PC.Utilities.DeepClone(data); Assert.IsTrue(data.CheckDeepClone(clone)); } [Serializable()] private class DummyCloneable { public int Data1; public string Data2; public object Data3; public List<int> Data4; public List<List<int>> Data5; public Dictionary<string, object> Data6; public DummyCloneable() { Data1 = 123; Data2 = "foo"; Data3 = new object(); Data4 = new List<int>(new int[] {1, 2, 3, 4, 5}); Data5 = new List<List<int>>(); Data5.Add(new List<int>(new int[] { 1, 2, 3, 4, 5 })); Data5.Add(new List<int>(new int[] { 1, 2, 3, 4, 5 })); Data5.Add(new List<int>(new int[] { 1, 2, 3, 4, 5 })); Data6 = new Dictionary<string, object>(); Data6["key1"] = "value1"; Data6["key2"] = 123; Data6["key3"] = 123.456D; Data6["key4"] = new object(); Data6["key5"] = Data5; } public bool CheckDeepClone(DummyCloneable obj) { if (obj.Data1 != this.Data1) return false; if (obj.Data2 != this.Data2) return false; if (obj.Data3.Equals(this.Data3)) return false; if (obj.Data4.Equals(this.Data4)) return false; for (int i = 0; i < this.Data4.Count; i++) if (obj.Data4[i] != this.Data4[i]) return false; if (obj.Data5.Equals(this.Data5)) return false; for (int i = 0; i < this.Data5.Count; i++) { if (obj.Data5[i].Equals(this.Data5[i])) return false; for (int j = 0; j < this.Data5[i].Count; j++) if (obj.Data5[i][j] != this.Data5[i][j]) return false; } if (obj.Data6.Equals(this.Data6)) return false; if (((string) obj.Data6["key1"]) != ((string) this.Data6["key1"])) return false; if (((int) obj.Data6["key2"]) != ((int) this.Data6["key2"])) return false; if (((double) obj.Data6["key3"]) != ((double) this.Data6["key3"])) return false; if (obj.Data6["key4"].Equals(this.Data6["key4"])) return false; List<List<int>> objValue5 = (List<List<int>>) obj.Data6["key5"]; List<List<int>> thisValue5 = (List<List<int>>) this.Data6["key5"]; if (objValue5.Equals(thisValue5)) return false; if (!objValue5.Equals(obj.Data5)) return false; for (int i = 0; i < thisValue5.Count; i++) { if (objValue5[i].Equals(thisValue5[i])) return false; for (int j = 0; j < thisValue5[i].Count; j++) if (objValue5[i][j] != thisValue5[i][j]) return false; } return true; } } On 10/30/07, David Nicholson <[EMAIL PROTECTED]> wrote: > No I hadn't thought of it. I haven't used serialisation very much, so I'm > a little wary about what might go on under the covers. Perhaps I shouldn't > be. > > I take care to follow a process, i.e. add a member, add an initialiser and > property if needed, add to Clone(). But as the class grows it would be > nice to have an automated check that these things have been done. Test > first doesn't work because you can't compile an initial failing test. > > Clone stands out because the effect of omitting a member is often subtle, > whereas a missing property is obvious immediately. > > Thanks > David. > > > > On Tue, 30 Oct 2007 16:03:38 +0800, =?ISO-8859-1?Q?S=E9bastien_Lorion?= > <[EMAIL PROTECTED]> wrote: > > >Have you thought about using serialisation for deep cloning (using > >MemoryStream) ? > > > >Sébastien > > > >On 10/29/07, David Nicholson <[EMAIL PROTECTED]> wrote: > >> I have some classes where I provide a Clone() method to provide a deep > >> copy of an instance, and would like to test that I haven't added a > member > >> to the class without also adding it to Clone(). > >> > >> To test Clone() I set a non-default value for the member, then check > that > >> the cloned copy has that value. However if I forget to add it to Clone > (), > >> I'll probably also forget to add it to the test. > >> > >> Does anyone have a way to do this, other than the obvious one of being > >> more disciplined? > >> > >> Thanks > >> David. > >> > >> =================================== > >> This list is hosted by DevelopMentor(R) http://www.develop.com > >> > >> View archives and manage your subscription(s) at > http://discuss.develop.com > >> > > > > > >-- > >Sébastien > >www.sebastienlorion.com > > =================================== > This list is hosted by DevelopMentor(R) http://www.develop.com > > View archives and manage your subscription(s) at http://discuss.develop.com > -- Sébastien www.sebastienlorion.com =================================== This list is hosted by DevelopMentor® http://www.develop.com View archives and manage your subscription(s) at http://discuss.develop.com