Это разбивается следующим образом:
String s = "123";
Переменная s:
это будет использовать собственный размер указателя на текущей архитектуре (которая считается 32-битной, если ОС 32-битная или процесс выполняется под WoW64), поэтому 32 бита или 64 бита соответственно. В этом случае s либо находится в стеке, либо зарегистрирован. Если бы вы поместили строковую ссылку в массив, тогда это пространство было бы использовано в куче.
Тот факт, что строка является объектом:
8 байтов служебных данных разделены на 4 байта для таблицы методов, которая удваивается как указание того, какой фактический тип является объектом, плюс 4 байта для некоторых служебных битов и синхронизирующий блок, который позволяет использовать его в качестве цели оператора блокировки.
Строка всегда заканчивается нулевым символом (хотя это деталь реализации, не являющаяся частью контракта среды выполнения), так что ее можно использовать непосредственно со строкой apis в стиле C, символы UTF-16, поэтому два байта на символ в смысле .Net использует символ (подробности того, почему это сложно и требует перехода к Unicode, я опущу).
Строки дополнительно содержат следующее:
Версии .Net до 4.0
- int для длины строки в символах
- int для длины базового массива, содержащего символы
- символ, который является первым символом в строке (последующие символы идут сразу после него) или нулевой символ для пустой строки
Строка может потреблять вдвое больше памяти, необходимой для фактического хранения массива символов, необходимого в соответствии со способом работы StringBuilder
Таким образом, сама строка будет занимать от 16 + (2 * n) + 2 до 16 + (4 * n) + 2 байта в куче в зависимости от того, как она была создана.
Версии .Net начиная с 4.0 и выше
- int для длины строки в символах
- символ, который является первым символом в строке (последующие символы идут сразу после него) или нулевой символ для пустой строки
Сама строка будет занимать как минимум 12 + (2 * n) + 2 байта в куче.
Обратите внимание, что в обоих случаях строка может занимать немного больше фактического пространства, чем она использует, в зависимости от того, какое выравнивание применяет среда выполнения, это, вероятно, будет не больше, чем IntPtr.Size.
Это может быть еще сложнее из-за интернирования строк (когда два отдельных экземпляра в конечном итоге указывают на одну и ту же строку, так как она неизменна), поскольку теоретически вы должны разделить служебные данные кучи (плюс служебные данные интерна) на число «независимых» ссылки на строку.
для дальнейшего обсуждения этого взгляните на эту статью . Однако обратите внимание, что эта статья устарела для изменений в 4.0.