c # клонировать список перекрестных ссылок

#c# #list #clone

#c# #Список #клонировать

Вопрос:

У меня есть список myItems. MyItem может ссылаться, а может и не ссылаться на свои одноранговые узлы.

 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 ----  
  

Мне нужно создать клон всего списка. Каждый MyItem в новом списке является новой копией myItems в старом списке (без ссылок), и все ссылки в новом списке должны указывать на элементы в новом списке. В конце новый список должен работать, даже если старый список и старые myItems полностью удалены.

Я внедрил интерфейс ICloneable в MyItem, чтобы элемент можно было клонировать, вызвав MyItem.Clone(). Однако клонированная копия по-прежнему ссылается на myItems в старом списке.

Как я могу обновить ссылки на myItems объектами в новом списке? Пример кода был бы высоко оценен.

Комментарии:

1. Мне почти интересно, нужно ли вам клонировать список, а не элементы в списке…

Ответ №1:

Что вы просто делаете, это сериализуете свой список в поток памяти, десериализуете его обратно и создаете клон. Поскольку каждый объект сериализуется только один раз, ваше поле RefTo будет сохранено в клонированной копии по вашему желанию, включая циклические ссылки

 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);
            }
        }
    }
}
  

Комментарии:

1. 1, вероятно, самый простой способ вместо написания метода DeepCopy (который может быть быстрее? но определенно очень сложно, особенно с перечислимыми и т.д.)

2. как насчет циклических ссылок?

3. никогда не думал таким образом. это потрясающе!