Удаление объектов с связями между собой

Суть вопроса. Не могу придумать адекватный подход удаления. В моей ситуации имеются сущности допустим коробка. В коробке могут лежать ещё коробки и тд. В одной коробке может лежать несколько, а в них ещё и тд. Как корректно удалить все. Если к примеру я удаляю самую первую коробку, в которой может лежать N коробок, в которых ещё могут лежать и тд. Все коробки лежат в List<Box>. Пользователь вводит имя коробки, которую необходимо удалить. И нужно удалить все коробки, которые лежат внутри.

public class Box
{
    public string NameBox{get;set;}

    public string RootNameBox{get;set;}
}

Привел пример класса, которые реализует эту зависимость.


Ответы (1 шт):

Автор решения: EvgeniyZ

Если у вас нет какой либо связанности между объектами (что зря), то ваш алгоритм должен быть примерно такой:

  • Берем нужную коробку на удаление.
  • Отдаем ее методу удаления.
    • Метод удаления ищет коробку/коробки, которые ссылаются на эту коробку удаления и рекурсивно вызывает самого себя.

Простой пример подобной реализации:

  • Ваш класс коробки (я добавил лишь конструктор)

    public class Box
    {
        public Box(string name, string rootBox = default)
        {
            NameBox = name;
            RootNameBox = rootBox;
        }
    
        public string NameBox { get; set; }
    
        public string RootNameBox { get; set; }
    }
    
  • Глобальный список всех коробок (если он не глобальный, то скорей всего придется передавать в метод параметром.

    static List<Box> boxes = new List<Box>
        {
            new Box("box1"),
            new Box("box2", "box1"),
            new Box("box3", "box2"),
            new Box("box4")
        };
    
  • Некий метод удаления (набросал его быстро, чисто показать пример подобного, если в 1 коробке может быть несколько коробок, то берите не первую, а все найденные и прогоняйте их циклом через метод.

    static void Delete(Box box)
    {
        var rootBox = boxes.FirstOrDefault(x => x.RootNameBox == box.NameBox);
        if (rootBox != null)
        {
            Delete(rootBox);
        }
    
        boxes.Remove(box);
    }
    
  • Ну и вызов.

    var firstBox = boxes.FirstOrDefault(x => x.NameBox == "box1");
    Delete(firstBox);
    

Имея все это, мы можем приукрасить все и сделать например метод расширения:

public static class Ext
{
    public static void DeleteBox(this List<Box> boxes, string boxName)
    {
        DeleteBox(boxes, boxes.FirstOrDefault(x => x.NameBox == boxName));
    }

    public static void DeleteBox(this List<Box> boxes, Box box)
    {
        if (box == null) return;

        var rootBox = boxes.FirstOrDefault(x => x.RootNameBox == box.NameBox);
        if (rootBox != null)
        {
            boxes.DeleteBox(rootBox);
        }

        boxes.Remove(box);
    }
}

Тогда вызов будет вообще:

boxes.DeleteBox("box1");

В общем саму суть рекурсии вы поняли, дальше сами дорабатывайте как вам надо. Удачи!


А что ты говорил про связи? Не мог бы подробнее?

Сейчас вы совершенно не знаете что за коробка у вас например будет в box1, ибо только box2 знает о том, что у нее есть "предок". На мой взгляд правильней будет переписать класс коробки на нечто подобное:

public class Box
{
    public Box(string name, Box rootBox = default)
    {
        NameBox = name;
        RootBox = rootBox;
    }

    public string NameBox { get; set; }

    public Box RootBox { get; set; }
}

Теперь основная коробка знает о том, что у нее есть дочерняя коробка и так у вас уже выстраивается цепочка зависимостей (box1.RootBox.RootBox.RootBox...).

И тогда нам уже не надо будет искать объект по имени, нам достаточно взять нужную коробку и удалить ее:

static void Delete(Box box)
{
    if (box.RootBox != null)
        Delete(box.RootBox);

    boxes.Remove(box);
}

Инициализация тут будет тогда примерно следующая:

var box4 = new Box("box4");
var box3 = new Box("box3");
var box2 = new Box("box2", box3);
var box1 = new Box("box1", box2);

boxes = new List<Box> { box1, box2, box3, box4 };
  • box1 ссылается на box2.
  • box2 ссылается на box3.
  • box3 и box4 являются простыми коробками, без ссылок.

Вызываем метод удаления для удаления первой коробки:

Delete(box1);

и в результате у нас останется только box4.

→ Ссылка