Я думаю о создании постоянной коллекции (списков или других) в C #, но я не могу найти хороший API.
Я использую ' persistent ' в смысле Clojure : постоянный список - это список, который ведет себя так, как если бы он имел семантику значений вместо ссылочной семантики, но ненесут накладные расходы на копирование типов больших значений.Постоянные коллекции используют функцию копирования при записи для совместного использования внутренней структуры.Псевдокод:
l1 = PersistentList()
l1.add("foo")
l1.add("bar")
l2 = l1
l1.add("baz")
print(l1) # ==> ["foo", "bar", "baz"]
print(l2) # ==> ["foo", "bar"]
# l1 and l2 share a common structure of ["foo", "bar"] to save memory
Clojure использует такие структуры данных, но дополнительно в Clojure все структуры данных являются неизменяемыми.Существуют некоторые издержки при выполнении всего, что происходит при копировании при записи, поэтому Clojure предлагает обходной путь в виде переходных структур данных, которые вы можете использовать, если уверены, что не делитесь структурой данных с кем-либо еще.Если у вас есть единственная ссылка на структуру данных, почему бы не изменить ее напрямую, а не проходить через все издержки копирования при записи.
Один из способов получить это повышение эффективности - это сохранить счетчик ссылок на вашем компьютере.структура данных (хотя я не думаю, что Clojure работает таким образом).Если refcount равен 1, вы держите единственную ссылку, поэтому делайте обновления деструктивно.Если refcount выше, кто-то другой также имеет ссылку на него, которая должна вести себя как тип значения, поэтому копируйте при записи, чтобы не мешать другим ссылкам.
В API для такой структуры данных можно выставить пересчет, что делает API менее пригодным для использования, или невозможно выполнить пересчет, что приведет к ненужным издержкам копирования при записи, если каждая операция является COW', или API теряет свое поведение типа значения, и пользователь должен решить, когда делать COW вручную.
Если бы в C # имелись конструкторы копирования для структур, это было бы возможно.Можно определить структуру, содержащую ссылку на реальную структуру данных, и выполнить все вызовы incref () / decf () в конструкторе копирования и деструкторе структуры.
Есть ли способ сделать что-то вроде подсчета ссылок или конструктора структурного копирования автоматически в C #, не беспокоя пользователей API?
Редактировать:
- Просто чтобы прояснить, я просто спрашиваю об API.У Clojure уже есть реализация этого, написанная на Java.
- Такой интерфейс, безусловно, можно создать, используя структуру со ссылкой на реальную коллекцию, которая используется COW в каждой операции.Использование пересчёта было бы оптимизацией, чтобы избежать ненужного COWing, но, очевидно, невозможно с нормальным API.