C# - 字符串实际上是一个字符数组还是只有一个索引器?

Kal*_*mro 16 c# arrays string

由于在C#中可以使用以下代码,因此我认为string是否实际上是一个chars数组:

string a="TEST";
char C=a[0]; // will be T
Run Code Online (Sandbox Code Playgroud)

Fac*_*Vir 18

System.String不是Char的.NET数组,因为这样:

char[] testArray = "test".ToCharArray();

testArray[0] = 'T';
Run Code Online (Sandbox Code Playgroud)

会编译,但是这个:

string testString = "test";

testString[0] = 'T';
Run Code Online (Sandbox Code Playgroud)

将不会.字符串数组是可变的,字符串不是.此外,string is Array返回false,同时char[] is Array返回true.


小智 15

不,这不是一个阵列.但它确实有一个索引器.两全其美.

  • 严格来说,"字符串"是字符"向量"的语法糖.它是一个对象,它存储对以null结尾的字符集开头的引用.字符串的实例,即内存中的字符集,是不可变的; 看起来你改变字符串(追加,大写,替换等)实际上导致创建的字符串的新实例及其引用放入字符串,旧字符串是GCed.这就是为什么像StringBuilder这样的构造,它在构建字符串时将数据保持在更可变的状态,这是很好的做法. (3认同)
  • 他们确实有固定的大小。无法调整字符串的大小,因此它们对我而言似乎并不那么困难。 (2认同)

Sco*_*man 5

.NET中的字符串由System.String类支持,该类在内部使用一堆不安全的方法,使用标准的C内存操作技术对实际的字符串数据进行指针操作.

String类本身不包含数组,但它确实有一个索引属性,它可以让你仿佛它是一个阵列处理数据.


Con*_*rix 5

在斯科特·多曼(Scott Dorman)和古法(Gufa)的回答中加点说明。如果在字符串“ abcd”上使用Windbg和!DumpObject,则会得到类似的信息。

0:000> !do 01139b24
Name: System.String
MethodTable: 79330a00
EEClass: 790ed64c
Size: 26(0x1a) bytes
 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: abcd
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
79332c4c  4000096        4         System.Int32  1 instance        5 m_arrayLength
79332c4c  4000097        8         System.Int32  1 instance        4 m_stringLength
793316e0  4000098        c          System.Char  1 instance       61 m_firstChar
79330a00  4000099       10        System.String  0   shared   static Empty
    >> Domain:Value  00181b38:01131198 <<
79331630  400009a       14        System.Char[]  0   shared   static WhitespaceChars
    >> Domain:Value  00181b38:011318b8 <<
Run Code Online (Sandbox Code Playgroud)

您会注意到它只有三个实例字段。m_arrayLength,m_stringLength和m_firstChar。它不包含实例System.Char []其他2个字段是静态共享的,因此每个System.String具有相同的Empty字符串和WhitespaceChar Char Array。

如果使用DumpByte跟随它,您将看到堆中的字符串数据(在本例中为abcd),该数据当然从偏移量0x0c(m_firstChar)开始,为8字节宽(对于unicode,m_stringLength 4 x 2)。

0:000> db 01139b24 L1A

01139b24  00 0a 33 79 05 00 00 00-04 00 00 00 61 00 62 00  ..3y........a.b.
01139b34  63 00 64 00 00 00 00 00-00 00                    c.d......
Run Code Online (Sandbox Code Playgroud)

正如Scott所说,如果您要查看SSCLI,要么运行不安全的代码,要么使用指针技术通过m_firstChar和m_stringLength读取数据。