Особенности Строк В .Net

Строковый тип данных является одним из наиболее важных в любом языке программирования.

Без использования этого типа данных вряд ли можно написать полезную программу.

Однако многие разработчики не знают некоторых нюансов, связанных с этим типом.

Итак, давайте посмотрим на некоторые возможности этого типа в .

NET.



Итак, начнем с представления строк в памяти.

В .

NET строки упорядочиваются в соответствии с правилом BSTR (базовая строка или двоичная строка).

Этот метод представления строковых данных используется в COM (слово «базовый» из языка программирования VisualBasic, в котором оно изначально использовалось).

Как известно в C/C++, PWSZ используется для представления строк, что означает Указатель на строку расширенных символов, завершающуюся нулем .

При таком расположении в памяти в конце строки стоит символ, заканчивающийся нулем, по которому мы можем определить конец строки.

Длина строки в PWSZ ограничена только объемом свободной памяти.



Особенности строк в .
</p><p>
NET

С BSTR дела обстоят немного иначе.



Особенности строк в .
</p><p>
NET

Основные особенности BSTR-представления строки в памяти:

  1. Длина строки ограничена определенным числом, в отличие от PWSZ, где длина строки ограничена наличием свободной памяти.

  2. Строка BSTR всегда указывает на первый символ в буфере.

    PWSZ может указывать на любой символ в буфере.

  3. BSTR всегда имеет нулевой символ в конце, как и PWSZ, но в отличие от последнего это допустимый символ и может появляться в любом месте строки.

  4. Благодаря наличию нулевого символа в конце BSTR совместим с PWSZ, но не наоборот.
Итак, строки в .

NET представлены в памяти согласно правилу BSTR. Буфер содержит четырехбайтовую строку, за которой следуют двухбайтовые строковые символы UTF-16, за которыми следуют два нулевых байта (\u0000).

Использование такой реализации имеет ряд преимуществ: длину строки не нужно пересчитывать; он хранится в заголовке, строка может содержать нулевые символы где угодно, и, что наиболее важно, адрес строки (закрепленный) можно легко передать в неуправляемый код, где ожидается WCHAR*.

Давайте двигаться дальше.



Сколько памяти занимает строковый объект?

Мне попадались статьи, где было написано, что размер строкового объекта равен size = 20 + (длина/2)*4, но эта формула не совсем корректна.

Начнем с того, что строка является ссылочным типом, поэтому первые 4 байта содержат SyncBlockIndex, а вторые 4 байта содержат указатель на тип.

Размер строки = 4 + 4 + .

Как уже говорилось выше, в буфере сохраняется длина строки — это поле int, а это значит еще 4 байта.

Размер строки = 4 + 4 + 4 +.

Чтобы быстро передать строку в неуправляемый код (без копирования), в конце каждой строки стоит символ с нулевым завершением, который занимает 2 байта, что означает Размер строки = 4 + 4 + 4 + 2 +.

Остается помнить, что каждый символ в строке находится в кодировке UTF-16, а значит, тоже занимает 2 байта, поэтому Размер линии = 4 + 4 + 4 + 2 + 2 * длина = 14 + 2 * длина Учтем еще один нюанс, и мы на месте.

А именно, менеджер памяти в CLR выделяет память кратно 4 байтам (4, 8, 12, 16, 20, 24,.

), то есть если длина строки в сумме занимает 34 байта, то Будет выделено 36 байт. Нам нужно округлить наше значение до ближайшего большего, кратного четырем, для этого нам понадобится: Размер строки = 4 * ((14 + 2 * длина + 3) / 4) (деление естественно целочисленное) Проблема с версией: В .

NET до версии 4 класс String хранит дополнительное поле m_arrayLength типа int, занимающее 4 байта.

Это поле представляет собой реальную длину буфера, выделенного для строки, включая null — завершающий символ, то есть длину + 1. В .

NET 4.0 это поле удалено из класса, в результате чего объект строкового типа принимает на 4 байта меньше.

Размер пустой строки без поля m_arrayLength (то есть в .

NET 4.0 и выше) = 4 + 4 + 4 + 2 = 14 байт, а с этим полем (то есть ниже .

NET 4.0) = 4. + 4 + 4 + 4 + 2 = 18 байт. Если округлить на 4 байта, то соответственно 16 и 20 байт.

Строковые функции

До сих пор мы рассматривали, как представляются строки и сколько памяти они на самом деле занимают. Теперь поговорим об их особенностях.

Основные возможности строк в .

NET:

  1. Это ссылочные типы.

  2. Они неизменны.

    Как только мы создадим строку, мы больше не сможем ее изменить (справедливым образом).

    Каждый вызов метода этого класса возвращает новую строку, а предыдущая строка становится объектом сбора мусора.

  3. Они переопределяют метод Object.Equals, чтобы он сравнивал не значения ссылок, а значения символов в строках.

Давайте рассмотрим каждый пункт более подробно.



Строки являются ссылочными типами

Строки являются настоящими ссылочными типами, то есть они всегда размещаются в куче.

Многие люди путают их с типами значений, потому что они ведут себя одинаково, например, они неизменяемы и сравниваются по значению, а не по ссылке, но помните, что это ссылочный тип.



Строки неизменяемы

Строки неизменяемы.

Это было сделано не просто так.

Неизменяемость строк имеет множество преимуществ:

  • Тип string является потокобезопасным, поскольку ни один поток не может изменить содержимое строки.

  • Использование неизменяемых строк снижает нагрузку на память, поскольку нет необходимости хранить два экземпляра одной и той же строки.

    В этом случае потребляется меньше памяти и сравнение происходит быстрее, поскольку требуется только сравнение ссылок.

    Механизм, реализующий это в .

    NET, называется string interning (пул строк), о нем мы поговорим чуть позже.

  • Передавая неизменяемый параметр методу, нам не нужно беспокоиться о его изменении (если, конечно, он не был передан как ссылка или out).

Структуры данных можно разделить на два типа – эфемерные и постоянные.

Фемеральные — это структуры данных, которые хранят только свою последнюю версию.

Постоянные структуры — это те, которые сохраняют все свои предыдущие версии при изменении.

Последние фактически неизменяемы, поскольку их операции не меняют существующую структуру, а вместо этого возвращают новую структуру, основанную на предыдущей.

Учитывая, что строки неизменяемы, они могли бы быть постоянными, но это не так.

В .

NET строки эфемерны.

Подробнее о том, почему это так, вы можете прочитать в книге Рика Липперта.

связь Для сравнения возьмем строки Java. Они неизменяемы, как и в .

NET, но также и постоянны.

Реализация класса String в Java выглядит следующим образом:

   

public final class String

Теги: #строки #структура данных #структура данных #функции #.

NET #C++

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.