Совместное использование символьного буфера между строками C # - PullRequest
3 голосов
/ 17 июня 2009

Возможно ли это? Учитывая, что C # использует неизменяемые строки, можно было бы ожидать, что будет метод, аналогичный следующему:

var expensive = ReadHugeStringFromAFile();
var cheap = expensive.SharedSubstring(1);

Если такой функции нет, зачем беспокоиться о том, чтобы сделать строки неизменяемыми? Или, альтернативно, если строки уже неизменны по другим причинам, почему бы не предоставить этот метод?

Конкретная причина, по которой я это изучаю, - это анализ файла. Простые парсеры с рекурсивным спуском (например, сгенерированные TinyPG или легко написанные вручную) повсеместно используют Substring. Это означает, что если вы дадите им большой файл для анализа, отток памяти будет невероятным. Конечно, есть обходные пути - в основном сверните свой собственный класс SubString, а затем, конечно же, забудьте о возможности использовать методы String, такие как StartsWith, или библиотеки String, такие как Regex, так что вам нужно также свернуть их собственную версию. Я предполагаю, что генераторы синтаксических анализаторов, такие как ANTLR, в основном делают это, но мой формат достаточно прост, чтобы не оправдать использование такого инструмента монстра. Даже TinyPG, вероятно, является излишним.

Кто-нибудь, пожалуйста, скажите мне, что я пропускаю какой-то очевидный или не очень очевидный стандартный вызов метода C # где-то ...

Ответы [ 6 ]

5 голосов
/ 17 июня 2009

Нет, ничего такого нет.

. NET строки содержат свои текстовые данные напрямую, в отличие от строк Java, которые имеют ссылку на массив символов, смещение и длину.

Оба решения имеют "выигрыши" в одних ситуациях и потери в других.

Если вы абсолютно уверены, что для вас это убийца, вы можете реализовать строку в стиле Java для использования в собственных внутренних API.

2 голосов
/ 17 июня 2009

Насколько я знаю, все большие парсеры используют потоки для анализа. Разве это не подходит для вашей ситуации?

1 голос
/ 17 июня 2009

.NET Framework поддерживает интернирование строк . Это частичное решение, но оно не дает возможности повторно использовать части строки. Я думаю, что повторное использование подстроки вызовет некоторые проблемы, не такие уж и очевидные на первый взгляд. Если вам приходится много манипулировать строками, используйте StringBuilder .

0 голосов
/ 17 июня 2009

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

string text = myCheapObject;

и все будет работать без проблем, как если бы это была настоящая строка. Добавление поддержки для нескольких удобных методов, таких как StartsWith, будет быстрым и легким (все они будут одним вкладышем).

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

0 голосов
/ 17 июня 2009

Ну, вы можете использовать «небезопасно» для управления памятью самостоятельно, что может позволить вам делать то, что вы ищете. Также класс StringBuilder отлично подходит для ситуаций, когда необходимо многократно манипулировать строкой, поскольку он не создает новую строку при каждой манипуляции.

0 голосов
/ 17 июня 2009

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

Что нужно, это Структура данных Rope , неизменная структура данных, которая поддерживает O (1) concats и O (log n) подстрок. Я не могу найти C # реализации веревки, но здесь Java .

За исключением этого, нет ничего плохого в использовании TinyPG или ANTLR, если это самый простой способ добиться цели.

...