ОБНОВЛЕНИЕ: мне очень понравился этот вопрос, я просто написал в блоге. См. Строки, неизменность и постоянство
Краткий ответ: O (n) - это O (1), если n не становится большим. Большинство людей извлекают крошечные подстроки из крошечных строк, поэтому то, как сложность асимптотически возрастает, составляет полностью не имеет значения .
Длинный ответ:
Неизменяемая структура данных, построенная таким образом, что операции над экземпляром позволяют повторно использовать память оригинала с небольшим объемом (обычно O (1) или O (lg n)) копирования или нового выделения, называется «постоянная» неизменяемая структура данных. Строки в .NET являются неизменяемыми; Ваш вопрос по сути "почему они не являются постоянными"?
Потому что, когда вы смотрите на операции, которые обычно выполняются над строками в программах .NET, во всех соответствующих случаях вряд ли хуже просто создать совершенно новую строку. Стоимость и сложность построения сложной постоянной структуры данных не окупаются.
Люди обычно используют «подстроку» для извлечения короткой строки - скажем, десяти или двадцати символов - из несколько более длинной строки - может быть, пару сотен символов. У вас есть строка текста в файле, разделенном запятыми, и вы хотите извлечь третье поле, которое является фамилией. Длина строки может составить пару сотен символов, а название - пару десятков. Выделение строк и копирование памяти из пятидесяти байтов на современных аппаратных средствах удивительно быстро . То, что создание новой структуры данных, состоящей из указателя на середину существующей строки и длины, равно и удивительно быстро, не имеет значения; «достаточно быстро» по определению достаточно быстро.
Извлекаемые подстроки, как правило, имеют небольшой размер и короткий срок службы; сборщик мусора скоро вернет их, и они не заняли много места в куче. Поэтому использование постоянной стратегии, которая поощряет повторное использование большей части памяти, также не является победой; все, что вы сделали, - замедлили сборщик мусора, потому что теперь он должен беспокоиться о работе с внутренними указателями.
Если бы операции с подстрокой, которые люди обычно выполняли со строками, были совершенно другими, то имело бы смысл придерживаться постоянного подхода. Если бы у людей обычно были строки из миллионов символов, и они извлекали тысячи перекрывающихся подстрок с размерами в диапазоне сотен тысяч символов, и эти подстроки долгое время жили в куче, тогда было бы разумно использовать постоянную подстроку. подход; это было бы расточительно и глупо не делать этого. Но большинство программистов, занимающихся бизнесом, не делают ничего, даже смутно подобного рода . .NET не является платформой, адаптированной для нужд проекта «Геном человека»; Программисты анализа ДНК должны решать проблемы с этими характеристиками использования строк каждый день; хорошие шансы, что вы нет. Те немногие, кто создает свои собственные постоянные структуры данных, которые близко соответствуют их сценариям использования.
Например, моя команда пишет программы, которые на лету анализируют код C # и VB по мере его ввода. Некоторые из этих файлов кода огромны , и поэтому мы не можем делать O (n) манипуляции со строками для извлечения подстрок или вставки или удаления символов. Мы создали ряд постоянных неизменяемых структур данных для представления изменений в текстовом буфере, что позволяет нам быстро и эффективно повторно использовать массив существующих строковых данных и существующих лексических и синтаксических анализов по типичным редактировать. Это была трудная проблема, и ее решение было узко приспособлено для конкретной области редактирования кода на C # и VB. Было бы нереально ожидать, что встроенный строковый тип решит эту проблему для нас.