Во-первых, обратите внимание, что разница между List<string>
, созданным в правильном размере , и string[]
(того же размера) несущественна для любого нетривиального размера;List<T>
на самом деле просто модная оболочка для T[]
с возможностями вставки / изменения размера / и т.д.Если вам нужно только хранить данные: T[]
нормально, но обычно List<T>
.
Что касается строки - это не C #, который резервирует что-либо - это .NET, который определяет, чтоstring
- это объект, который внутренне имеет длину (int
) плюс память для данных char
, 2 байта на char
.Но: объекты в .NET имеют заголовки объектов, отступы / выравнивание и т. Д., И, что важно, a минимальный размер .Так что да, они занимают больше памяти, чем просто необработанные данные, которые вы пытаетесь представить.
Если вам нужны только фактические данные , вы можете хранить данные не как string
, но в качестве необработанной памяти - либо просто большой byte[]
или byte*
, либо в виде парной пары int[]
/ int*
(для длин и / или смещений на странице) и char[]
/ char*
(для фактических символьных данных) или byte[]
/ byte*
, если вы можете работать с закодированными данными (т.е. вы в основном заинтересованы в работе ввода-вывода).Однако работать с такой формой будет крайне неудобно - практически ни один из распространенных API не захочет играть с вами, если вы не говорите в string
.Существуют некоторые API, которые принимают необработанные байтовые / символьные данные, но в основном это API-интерфейсы кодировщика / декодера и некоторые API-интерфейсы ввода-вывода.Итак, еще раз: если это не то, что вы делаете: это не закончится хорошо .Совсем недавно появилось несколько Span<char>
/ Span<byte>
API, которые сделали бы это немного менее неудобным (если вы можете использовать последние сборки .NET Core и т. Д.), Но: я сильно подозреваю, что в большинствев общих случаях вам просто придется принять string
накладные расходы и жить с ними.