Вопрос по c# – Как типы String и Char хранятся в памяти в .NET?

11

Мне нужно хранить строку кода языка, такую как «en», которая всегда будет содержать 2 символа.

Является ли лучше определить тип как "String" или "Чар"?

private string languageCode;

против

private char[] languageCode;

Или есть другой, лучший вариант?

Как эти 2 хранятся в памяти? сколько байтов или битов для них будет выделено при назначении значений?

Там будет до 20 комбинаций. Не уверен, как такое перечисление хранится в памяти или лучше? The Light
@ Вильям в этом случае, пойти наbyteзанимает 1 байт. Я обновил свой ответ. Перечисления являются типами значений и будут существовать в стеке в области метода или внутри пространства кучи класса в области класса. Adam Houldsworth
@William Если производительность так важна, почему бы не объявитьenum LanguageCode : short и сохранить 2 байта? Adam Houldsworth
У меня очень напряженная логика, которая хранит тысячи таких в памяти, так что каждый помогает. The Light
Вы на самом деле доказали себе, что это проблема? Я очень редко обнаруживал необходимость беспокоиться о памяти при использовании строк, особенно таких маленьких. Если это не проявляется как проблема, тогда не беспокойтесь об этом, пока это не произойдет. Позже это легко исправить, если строки вызывают проблемы с памятью. В противном случае используйте строку и даже не думайте о проблемах с памятью. Russell Troywest

Ваш Ответ

5   ответов
4

Краткий ответ: используйте строку

Длинный ответ:

private string languageCode;

Строки AFAIK хранятся в виде массива символов с префиксом длины. Объект String создается в куче для поддержки этого необработанного массива. Но объект String - это гораздо больше, чем простой массив, он позволяет выполнять базовые строковые операции, такие как сравнение, конкатенация, извлечение подстроки, поиск и т. Д.

В то время как

private char[] languageCode;

будет храниться в виде массива символов, т. е. в куче будет создан объект массива, который затем будет использоваться для управления вашими персонажами. Но у него все еще есть атрибут длины, который хранится внутри, поэтому нет очевидной экономии памяти по сравнению со строкой. Хотя, предположительно, Array проще, чем String, и может иметь меньше внутренних переменных, тем самым предлагая меньший отпечаток памяти (это необходимо проверить).

Но OTOH вы теряете возможность выполнять строковые операции с этим массивом символов. Даже такие операции, как сравнение строк, теперь становятся громоздкими. Короче говоря, используйте строку!

0

Строки действительно имеют размер служебной информации, равный одной длине указателя, то есть 4 байта для 32-битного процесса, 8 байтов для 64-битного процесса. Но опять же, строки предлагают гораздо больше взамен, чем массивы символов.

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

1

How are these 2 stored in memory? how many bytes or bits for will be allocated to them when values assigned?

каждыйinstance в .NET хранится следующим образом: одинIntPtrполе для идентификатора типа; еще один для блокировки на экземпляре; остаток - данные поля экземпляра, округленные доIntPtrразмер Следовательно, на 32-битной платформе каждыйinstance занимает 8 байт + данные поля.

Это относится как кstring иchar[], Оба из них также хранят длину данных в виде целого числа размера IntPtr, за которым следуют фактические данные. Таким образом, двухсимвольныйstring и двухсимвольныйchar[]на 32-битной платформе будет занимать 8 + 4 + 4 = 16 байт.

Единственный способ уменьшить это при сохранении ровно двух символов - это сохранить фактические символы или структуру, содержащую символы, в поле или массиве. Все они будут использовать только 4 байта для символов:

// Option 1
class MyClass
{
    char Char1, Char2;
}

// Option 2
class MyClass
{
    CharStruct chars;
}
...
struct CharStruct { public char Char1; public char Char2; }

MyClass закончится использованием 8 байтов (на 32-битной машине) на экземпляр плюс 4 байта для символов.

// Option 3
class MyClass
{
    CharStruct[] chars;
}

Это будет использовать 8 байтов для служебных данных MyClass, плюс 4 байта дляchars referenceплюс 12 байтов для заголовка массива плюс 4 байта наCharStruct в массиве.

Error: User Rate Limit Exceededmsdn.microsoft.com/en-us/magazine/cc163791.aspxError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
9

How They Are Stored

Обаstring иchar[] хранятся в куче - поэтому хранилище то же самое. Внутренне я бы предположилstring просто прикрытие дляchar[] сlots дополнительного кода, чтобы сделать его полезным для вас.

Также, если у вас много повторяющихся строк, вы можете использоватьинтернирование уменьшить объем памяти этих строк.

The Better Option

Я бы предпочел строку - сразу становится более очевидно, что это за тип данных и как вы собираетесь его использовать. Люди также более привыкли к использованию строк, поэтому ремонтопригодность не пострадает. Вы также получите большую выгоду от всего стандартного кода, который был сделан для вас. Microsoft также приложила много усилий, чтобыstring Тип не боров производительности.

The Allocation Size

Я понятия не имею, сколько выделено, я считаю, что строки достаточно эффективны в том смысле, что они выделяют достаточно только для хранения символов Unicode - поскольку они являются неизменяемыми, это безопасно сделать. Размеры массивов также не могут быть изменены без выделения пространства в новом массиве, поэтому я снова предполагаю, что они получают только то, что им нужно.

Накладные расходы на массив .NET?

Alternatives

Исходя из вашей информации о том, что существует только 20 языковых кодов и производительность является ключевым, вы можете объявить свой собственный enum, чтобы уменьшить размер, необходимый для представления кодов:

enum LanguageCode : byte
{
    en = 0,
}

Это займет всего 1 байт, в отличие от 4+ на двоихchar (в массиве), но это ограничивает диапазон доступныхLanguageCode значения в диапазонеbyte - это более чем достаточно для 20 предметов.

Вы можете увидеть размер типов значений, используяsizeof() оператор:sizeof(LanguageCode), Перечисления - это не что иное, как базовый тип под капотом, по умолчанию ониint, но, как вы можете видеть в моем примере кода, вы можете изменить это с помощью & quot; наследования & quot; новый тип.

Error: User Rate Limit Exceededstackoverflow.com/questions/3669199/…Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
0

Если вы хотите хранить ровно 2 символа и делать это наиболее эффективно, используйте структуру:

struct Char2
{
 public char C1, C2;
}

Использование этой структуры обычно не приводит к выделению новой кучи. Он просто увеличит размер существующего объекта (на минимально возможное количество) или потребит пространство стека, что очень дешево.

Error: User Rate Limit Exceededstruct LanguageCodeError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededwhereError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceedednewError: User Rate Limit Exceeded

Похожие вопросы