Согласованность между списками C # - PullRequest
1 голос
/ 01 февраля 2012

Я пишу небольшой игровой движок для XNA.Прямо сейчас у моего менеджера сущностей есть список всех сущностей, которые он может обновлять и отображать.Скажем, однако, что я хочу разделить этот список на «подсписки».Возможно, некоторые объекты не требуют рендеринга, и поэтому мы хотели бы отделить объекты рендеринга от объектов без рендеринга, сохраняя при этом другой список, который показывает ВСЕ объекты для обновления.Так вот 3 списка.

Есть ли способ легко поддерживать согласованность между списками?Чтобы гарантировать, что одни и те же объекты упоминаются в обоих списках?(Не копия объекта?).В C ++ у нас был бы просто массив указателей на сущности, которые рендерится, и еще один для сущностей, которые не отображают.

Проблема не в том, чтобы поместить сущности в эти списки, а в том, чтобы избавиться от них.Чтобы уничтожить сущность, я просто устанавливаю bool «dispose» в значение true в этой сущности.Менеджер сущностей при циклическом просмотре всех сущностей удаляет ссылку на эту сущность, если для параметра dispose установлено значение true, а уборщик мусора уничтожает сущность, поскольку на нее больше не осталось ссылок.Должен ли я вручную просматривать все списки, имеющие отношение к сущностям, и удалять эту сущность из этих списков, чтобы все было согласованно?

еще один пример этой «проблемы» - с квад-деревьями.У меня есть 2D-игра, и я генерирую дерево квадов для всех сущностей.Сущности, которые лежат между 2 точками сетки, находятся в 2 ветвях дерева.как бы я удалить его с дерева?искать во всем дереве ссылки на эту сущность?кажется немного бессмысленным иметь четырехугольное дерево, если это так ..!

Ответы [ 5 ]

3 голосов
/ 01 февраля 2012

Рассмотрим вместо 3 списков, иметь один список и 2 запроса этого списка.

var list = GetYourMainList(); 
var renderableEntities = list.Where(item => item.IsRenderable); 
var nonrenderableEntities = list.Where(item => !item.IsRenderable); 

// work with the queries
foreach (var item in renderableEntities)
{
    // do whatever
}

Здесь вы можете выполнять итерацию по каждому запросу, результаты будут передаваться из основного списка, и любое обновление этого списка будет отражаться в результатах запроса по мере их повторения.Предостережение заключается в том, что список нельзя изменить (например, добавить или удалить из него), пока запросы повторяются.

0 голосов
/ 01 февраля 2012

Вы можете сделать так, чтобы ваша сущность выставляла событие «Уничтожение», которое запускается до его уничтожения. Тогда вы могли бы сделать так, чтобы метод Add вашего списка регистрировал обработчик событий с добавляемой сущностью, которая удалит сущность из списка до ее удаления.

0 голосов
/ 01 февраля 2012

Если у вас есть элементы в нескольких списках, то да, если вы хотите удалить их, вы должны удалить их из всех списков, в которых они встречаются. Простой способ сделать это - назначить ответственность за удаление элементов самим элементам: например, элементы рендеринга удалят себя из списка элементов рендеринга, когда вы вызываете RemoveFromLists () для них.

Использование запросов, описанных Энтони Пеграмом, устраняет эту сложность, но неэффективно, если списки большие, поскольку они не могут обновляться постепенно.

Что касается квадродерев, простая вещь состоит в том, чтобы каждый элемент содержал список узлов квадродерева, в которых он встречается (или, если вы не хотите добавлять поле к вашим элементам, используйте Словарь). Затем их просто удалить из всех узлов, в которых они находятся за постоянное время.

0 голосов
/ 01 февраля 2012

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

0 голосов
/ 01 февраля 2012

Что касается вашей проблемы утилизации, вы можете реализовать IDisposable. Для ваших списков вы можете создать класс, содержащий два списка, и, если вам нужен весь список, реализовать перечислитель, который будет перечислять два списка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...