Search code examples
c#listclone

c# clone a cross-referencing list


I have a list of MyItems. MyItem may or may not refer to its peers.

List<MyItem> myList = new List<MyItem>();
myList.add(...)  //add all 8 items
myList[1].RefTo = myList[3];
myList[5].RefTo = myList[2];
myList[7].RefTo = myList[5];

        Item 0
        Item 1 ----+
  +---> Item 2     |
  |     Item 3 <---+
  |     Item 4 
  +---  Item 5 <---+
        Item 6     |
        Item 7 ----+ 

I need to make a clone of the whole list. Every MyItem in the new list is a new copy of the MyItems in the old list (not referencing) and all the references in the new list should point to the items in new list. At then end, the new list should work even the old list and the old MyItems are completely deleted.

I have implementd the ICloneable interface in MyItem so the item can be cloned by calling MyItem.Clone(). However, the cloned copy is still referencing to the MyItems in the old list.

How can I update the references of the MyItems with the objects in the new list? Sample code would be highly appreciated.


Solution

  • What you simply do is serialize your list to a memory stream and deserialize it back and create a clone. As each object is only serialized once your RefTo field will be preserved in the cloned copy as you wish including circular references

    namespace ConsoleApplication1
    {
        [Serializable]
        class MyItem
        {
            public int MyProperty { get; set; }
            public MyItem RefTo { get; set; }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                List<MyItem> list1 = new List<MyItem>();
                list1.Add(new MyItem() { MyProperty = 1 });
                list1.Add(new MyItem() { MyProperty = 2 });
                list1.Add(new MyItem() { MyProperty = 3 });
    
                list1[1].RefTo = list1[0];
                list1[2].RefTo = list1[1];
    
                using (MemoryStream stream = new MemoryStream())
                {
                    var bformatter = new BinaryFormatter();
                    bformatter.Serialize(stream, list1);
                    stream.Seek(0, SeekOrigin.Begin);
                    List<MyItem> clonedCopyList = (List<MyItem>)bformatter.Deserialize(stream);
                }
            }
        }
    }