Существует ли более подходящая / эффективная структура данных для очереди транзакций, чем использование списка.Я пытался использовать Очереди и Стеки, но ни один из них не соответствует требованиям.
Ниже я подробно изложил свою проблему с примерами, показывающими, почему я на данный момент получил Список.Любые предложения альтернативных структур данных (предпочтительно, но не ограничиваясь теми, которые имеют реализацию в .Net BCL) приветствуются.
Проблема
Поддерживать очередь транзакций Insert()
/ Delete()
операции, которые впоследствии будут сохранены в произвольном резервном хранилище, когда пользователь вызывает метод Commit()
, или отменяются, когда они вызывают метод Rollback()
.
Операции должны выполняться в состоянии в памяти затрагиваемого объектапоскольку последующие операции могут зависеть от состояния объекта, созданного предыдущими операциями.
Пример 1
У меня есть объект obj
, который начинается как пустая коллекция.Пользователь вставляет элемент i
, а затем удаляет элемент i
.
Затем он вызывает Rollback()
, учитывая следующие структуры данных для очереди: при откате происходит следующее:
- Очередь -
obj.Delete(i)
, obj.Insert(i)
-> неверно, поскольку obj
должен оставаться пустым после отката - Стек -
obj.Insert(i)
, obj.Delete(i)
-> правильно, поскольку obj
остается пустым - Список (Обратный обход) -
obj.Insert(i)
, obj.Delete(i)
-> правильно, поскольку obj
остается пустым
Если вместо этого они вызывают Commit()
, то происходит следующее:
- Очередь -
obj.Insert(i)
, obj.Delete(i)
-> правильно, поскольку obj
остается пустым - Стек -
obj.Delete(i)
, obj.Insert(i)
-> неверно, поскольку obj
не являетсяпусто - Список (Прямой обход) -
obj.Insert(i)
, obj.Delete(i)
-> правильно, поскольку obj
остается пустым
Так что в этом примере очередь работает для Commit()
, но неRollback()
и стек показывает обратное поведение , но оба неверны.Только List показывает правильное поведение, хотя обратите внимание, что для коммита мы пересекаем список в прямом направлении, в то время как для отката мы пересекаем список в обратном направлении.
Пример 2
Теперь рассмотрим сноваобъект obj
, который на этот раз начинается с отдельного элемента i
, содержащегося в нем.
На этот раз последовательность операций представляет собой удаление i
с последующей вставкой i
.
Если они вызывают Rollback()
, происходит следующее:
- Очередь -
obj.Insert(i)
, obj.Delete(i)
-> неверна, поскольку obj
заканчивается как пустой - Stack -
obj.Delete(i)
, obj.Insert(i)
-> правильно, поскольку obj
содержит один элемент i
все еще - Список (обратный путь) -
obj.Delete(i)
, obj.Insert(i)
-> правильно, поскольку obj
содержитодин элемент i
все еще
Если они вместо этого вызвали Commit()
, происходит следующее:
- Очередь -
obj.Delete(i)
, obj.Insert(i)
-> правильно с obj
содержит один элемент i
все еще - стек -
obj.Insert(i)
, obj.Delete(i)
-> incorrect, так как obj
заканчивается как пустой - List (Forward Traversal) -
obj.Delete(i)
, obj.Insert(i)
-> правильно, поскольку obj
содержит единственный элемент i
still
Как и в предыдущем примере, только использование списка является правильным в обоих случаях, но мы должны обходить его в разных направлениях в зависимости от того, совершаем ли мы коммит или откат.
Итог
При использованииСписок сам по себе не является неэффективным. Мне просто интересно, существует ли более подходящая структура данных, которая лучше подходит для моей проблемы?