Неизменяемые коллекции?
Я делаю большинство моих основных типов в моем приложении, неизменяемым. Но должны ли коллекции быть неизменными? Для меня это похоже на огромные накладные расходы, если я чего-то не упускаю.
Я говорю о коллекциях для хранения значений Point3 и т. д., которые могут быть добавлены в разное время. Поэтому, если в коллекции есть 1M значений, и вам нужно удалить 1 из них, вам придется создавать ту же коллекцию снова и снова, верно?
10 ответов
У Эрика Липперта есть серия о неизменности в C#, и если вы прочитаете ее полностью, он реализует пару разных неизменяемых коллекций:
- неизменяемость в C# Часть первая: виды неизменяемости
- неизменяемость в C# Часть вторая: простой неизменяемый стек
- неизменяемость в C# Часть третья: Ковариантный неизменяемый стек
- неизменяемость в C# Часть четвертая: неизменяемость Очередь
- неизменяемость в C# Часть пятая: LOLZ!
- неизменяемость в C# Часть шестая: простое двоичное дерево
- неизменяемость в C# Часть седьмая: подробнее о двоичных деревьях
- неизменяемость в C# часть восемь: еще больше на двоичных деревьях
- неизменность в C# Часть девятая: академическая? Плюс моя реализация дерева AVL
- неизменяемость в части C# Десять: двойная очередь
- неизменяемость в C# Part Eleven: рабочая двусторонняя очередь
immutable коллекции великолепны, особенно если ваше приложение уже использует неизменяемые типы и семантика.
.NET только что отправил свой первый immutable коллекции, который я предлагаю вам попробовать.
мой любимый трюк с коллекциями-просто никогда не передавать их. Если они существуют только внутри одного объекта, то их неизменность в основном не имеет значения (пока ваш содержащий объект не изменяет их, они не изменятся).
обычно ваша коллекция представляет что-то правильное? Это коллекция собак или счета-фактуры...
обычно есть вещь, которую вы можете сделать с коллекцией собак (стадо? кастрат?) или собрание счета-фактуры (оплачиваю?) Есть практически всегда операции, которые применяются ко всему списку объектов-операции, которые имеют функциональность за пределами отдельного счета-фактуры.pay () (например, гарантируя, что самые важные счета-фактуры оплачиваются первыми), без класса вокруг вашей коллекции действительно нет места для размещения этих операций.
также обычно имеет смысл иметь несколько переменных, связанных с вашей коллекцией-и снова без обертки вы всегда в конечном итоге помещаете их переменные в каком-то странном неестественном месте.
сначала это может показаться странным, но попробуйте пару раз, прежде чем судить.
Я согласен с комментариями Эрика О выборе правильного инструмента для задачи. Неизменность добавляет ценность, когда ваши цели включают предоставление четкой семантики идентичности или упрощение работы с реализацией в параллельной вычислительной среде. Неизменяемость также может помочь повысить производительность, разрешив оптимизацию, такую как кэширование или прозрачное проксирование.
на оборотной стороне, неизменяемость может также понести цену представления-особенно когда вы используете "копирование при записи" выкройка к модели "изменения".
вы должны решить почему вы хотите, чтобы ваши сущности/коллекции были неизменяемыми - и это поможет вам принять решение о том, делать это или нет.
Если вы только когда - либо добавляете/удаляете с начала или конца, вы можете обмануть-но в целом; да: подразумевается, что вам нужно создать новую коллекцию для каждого изменения.
Итак: вам нужно (эффективно) мутировать коллекции? Если да, и учитывая их размер: я бы соблазнился посмотреть на синхронизацию доступа (а не делать их должным образом неизменяемыми). Посмотреть lock
(Он же Monitor
).
таблица поиска сделает приличную неизменяемую коллекцию. Ему не нужно менять размер, и вы хотите, чтобы он был статичным, поэтому он быстро ищет сложные вычисления. Если вам нужно добавить что-то позже, я бы не стал беспокоиться о неизменности, это разрушает цель.
Это зависит от стиля, в котором написана/разработана ваша программа.
неизменяемая коллекция имеет смысл только тогда, когда вы программируете в стиле, зависящем от функционального программирования (императивно разработанные программы не должны их использовать).
и, как и в функциональных языках, Вы должны использовать связанные списки, которые могут быть построены в O (1) на элемент (cons
) и обрабатывать их функционально (рекурсии, построение новых списков из списков).
когда ваша программа требует императивных коллекций (массивов, векторов / списков), держите их изменяемыми.
вы можете определить свой открытый интерфейс как IEnumerable, но все же использовать изменяемую коллекцию в своей реализации.
все зависит от того, кто одновременно использует коллекции. Строки неизменяемы, чтобы предотвратить boo-boo, как два потока, пытающихся удалить первый символ одновременно.
Если у вас есть коллекция, в которую вы можете добавить элементы после ее создания, она не является неизменяемой