string内部的数据结构惊人的简单:
private int m_stringLength;
private char m_firstChar;
对于字符串的操作,内部都是unsafe code:
char* ap = &strA.m_firstChar
这里就暴露出string的不简单了。为什么m_firstChar(值类型char)的地址可以指代一个字符串?
char a = 'a';
char* pa = &a;
能通过pa得到"abcd"么,肯定不行啊。
所以,我们还是再深入看看,char到底是什么?
public struct Char
{
internal char m_value;
}
char 就是 System.Char 的别名,如果尝试自己定义类似的 struct,肯定是编译不过的,这里涉及到循环引用,编译器不能确定 struct 的大小。但对于内建类型,编译器能明确知道它的大小,会“跳过”检查。Char 没有构造函数,我们不知道他是怎么初始化,也不知道底层的数据结构,如何占用内存。
根据 string 的表现,可以猜测,在 CLR 内部,对于 char,实际上包含一个 char*** 指针。当表现为 Char时,只取一字节(char[0])。但不限于表面的一字节,char* 实际上可以是一个字符串。在 string的构造函数里(照样看不到),完成了内存分配,并将首地址包含在 m_firstChar 中(注意 m_value 的访问类型是internal ),并记下长度 m_stringLength,这样就能解释了。