String和Char类型如何在.NET中存储在内存中?

我需要存储一个语言代码字符串,例如“en”,它总是包含2个字符。

将类型定义为“String”或“Char”更好吗?

private string languageCode; 

VS

 private char[] languageCode; 

或者还有另一种更好的选择吗?

这些2如何存储在内存中? 分配值时,将为它们分配多少字节或位?

它们是如何存储的

stringchar[]都存储在堆上 – 因此存储是相同的。 在内部我会假设一个string只是char[]一个封面,有很多额外的代码使它对你有用。

此外,如果您有许多重复的字符串,您可以使用Interning来减少这些字符串的内存占用。

更好的选择

我倾向于使用字符串 – 数据类型是什么以及打算如何使用它会更加明显。 人们也更习惯使用字符串,因此可维护性不会受到影响。 您也将从为您完成的所有样板代码中受益匪浅。 微软也付出了很多努力来确保string类型不是性能损失。

分配大小

我不知道分配了多少,我相信字符串是非常有效的,因为它们只分配足够的存储Unicode字符 – 因为它们是不可变的,这样做是安全的。 如果不在新数组中分配空间,也无法调整数组的大小,因此我再次假设它们只获取所需内容。

.NET数组的开销?

备择方案

根据您的信息,只有20种语言代码和性能是关键,您可以声明自己的枚举,以减少代表代码所需的大小:

 enum LanguageCode : byte { en = 0, } 

对于两个char (在数组中),这只需要1个字节而不是4+,但它确实将可用的LanguageCode值的范围限制为byte范围 – 这对于20个项目来说足够大。

您可以使用sizeof()运算符来查看值类型的sizeof()sizeof(LanguageCode) 。 枚举只是底层的底层类型,它们默认为int ,但正如您在我的代码示例中所看到的,您可以通过“inheritance”新类型来更改它。

简答:使用字符串

答案很长:

 private string languageCode; 

AFAIK字符串存储为字符长度前缀字符。 在堆上实例化String对象以维护此原始数组。 但是String对象不仅仅是一个简单的数组,它还支持基本的字符串操作,如比较,连接,子字符串提取,搜索等

 private char[] languageCode; 

将被存储为一个字符数组,即将在堆上创建一个Array对象,然后它将用于管理您的字符。 但它仍然有一个内部存储的长度属性,因此与字符串相比,内存没有明显的节省。 虽然可能是一个数组比一个字符串更简单,并且内部变量可能更少,从而提供更低的内存占用量(这需要进行validation)。

但OTOH你失去了对这个char数组执行字符串操作的能力。 即使像字符串比较这样的操作现在变得很麻烦。 所以长话短说使用一个字符串!

这些2如何存储在内存中? 分配值时,将为它们分配多少字节或位?

.NET中的每个实例都存储如下:一个IntPtr -sized字段用于类型标识符; 还有一个用于锁定实例; 余数是实例字段数据四舍五入到IntPtr大小的数量。 因此,在32位平台上,每个实例占用8个字节+字段数据。

这适用于stringchar[] 。 这两者还将数据的长度存储为IntPtr大小的整数,然后是实际数据。 因此,在32位平台上,两个字符的string和两个字符的char[]将占用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 引用 ,加上12个字节用于数组的开销,加上4个字节用于数组中的每个CharStruct

如果要准确存储2个字符,并且最有效地执行,请使用结构:

 struct Char2 { public char C1, C2; } 

使用此结构通常不会导致新的堆分配。 它只会升级现有对象(以最小可能的数量)或消耗非常便宜的堆栈空间。

字符串确实具有一个指针长度的大小开销,即32位进程的4个字节,64位进程的8个字节。 但话说回来,字符串提供了比char数组更多的回报。

如果您的应用程序使用了许多短字符串,并且您不需要经常使用它们的字符串属性和方法,那么您可以安全地使用几个字节的内存。 但是如果要将它们中的任何一个用作字符串,首先必须创建一个新的字符串实例。 我无法看到这将如何帮助你安全足够的记忆值得麻烦。