I'd need to store a language code string, such as "en", which will always contains 2 characters.
Is it better to define the type as "String" or "Char"?
private string languageCode;
vs
private char[] languageCode;
Or is there another, better option?
How are these 2 stored in memory? how many bytes or bits for will be allocated to them when values assigned?
Short answer: Use string
Long answer:
AFAIK strings are stored as a length prefixed array of chars. A String object is instantiated on the heap to maintain this raw array. But a String object is much more than a simple array it enables basic string operations like comparison, concatenation, substring extraction, search etc
While
will be stored as an Array of chars i.e. an Array object will be created on the heap and then it will be used to manage your characters. But it still has a length attribute which is stored internally so there are no apparent savings in memory when compared to a string. Though presumably an Array is simpler than a String and may have fewer internal variables thus offering a lower memory foot print (this needs to be verified).
But OTOH you loose the ability to perform string operations on this char array. Even operations like string comparison become cumbersome now. So long story short use a string!
If you want to store exactly 2 chars, and do it most efficiently, use a struct:
Using this struct will generally not cause new heap allocations. It will just upsize an existing object (by the minimum possible amount) or consume stack space which is very cheap.
Every instance in .NET is stored as follows: one
IntPtr
-sized field for the type identifier; one more for locking on the instance; the remainder is instance field data rounded up to anIntPtr
-sized amount. Hence, on a 32-bit platform every instance occupies 8 bytes + field data.This applies to both a
string
and achar[]
. Both of these also store the length of the data as an IntPtr-sized integer, followed by the actual data. Thus, a two-characterstring
and a two-characterchar[]
, on a 32-bit platform, will occupy 8+4+4 = 16 bytes.The only way to reduce this when storing exactly two characters is to store the actual characters, or a struct containing the characters, in a field or an array. All of these would consume only 4 bytes for the characters:
MyClass
will end up using 8 bytes (on a 32-bit machine) per instance plus the 4 bytes for the chars.This will use 8 bytes for the MyClass overhead, plus 4 bytes for the
chars
reference, plus 12 bytes for the array's overhead, plus 4 bytes perCharStruct
in the array.Strings indeed have a size overhead of one pointer length, i.e. 4 bytes for a 32 bit process, 8 bytes for a 64 bit process. But then again, strings offer so much more in return than char arrays.
If your application uses many short strings and you don't need to use their string properties and methods that often, you could probably safe a few bytes of memory. But if you want to use any of them as a string, you will first have to create a new string instance. I can't see how this will help you safe enough memory to be worth the trouble.
How They Are Stored
Both the
string
and thechar[]
are stored on the heap - so storage is the same. Internally I would assume astring
simply is a cover forchar[]
with lots of extra code to make it useful for you.Also if you have lots of repeating strings, you can make use of Interning to reduce the memory footprint of those strings.
The Better Option
I would favour string - it is immediately more apparent what the data type is and how you intend to use it. People are also more accustomed to using strings so maintainability won't suffer. You will also benefit greatly from all the boilerplate code that has been done for you. Microsoft have also put a lot of effort in to make sure the
string
type is not a performance hog.The Allocation Size
I have no idea how much is allocated, I believe strings are quite efficient in that they only allocate enough to store the Unicode characters - as they are immutable it is safe to do this. Arrays also cannot be resized without allocating the space in a new array, so I'd again assume they grab only what they need.
Overhead of a .NET array?
Alternatives
Based on your information that there are only 20 language codes and performance is key, you could declare your own enum in order to reduce the size required to represent the codes:
This will only take 1 byte as opposed to 4+ for two
char
(in an array), but it does limit the range of availableLanguageCode
values to the range ofbyte
- which is more than big enough for 20 items.You can see the size of value types using the
sizeof()
operator:sizeof(LanguageCode)
. Enums are nothing but the underlying type under the hood, they default toint
, but as you can see in my code sample you can change that by "inheriting" a new type.