.NET中的字符串类型与字符数组的区别

11

我在工作中使用一些需要进行大量字符串解析等操作的程序已有一个月了。 我被建议使用 char 数组,而不是 string,因为 char 数组更快。 我明白 char 数组更快的原因,但是 string 类型的缓慢是由于什么引起的呢? 它实现了什么样的数据结构,是否有任何方法使它像 char 数组一样快?

2个回答

21
最明显的区别是,string是不可变的。因此,您无法修改它的部分,并且需要在每次修改时创建全新的副本。
字符串本身有一个非常特殊的实现(它是一个可变大小的类),并且没有由数组支持。我认为从字符串中只读访问 char 应该不会很慢。
因此,如果您想更改字符串的小部分,则需要使用 StringBuilderchar[]。在这两个选项中,char[] 是/曾经是更快的,因为 StringBuilder 具有额外的验证和间接性。但由于这是一项实现细节,自我上次测试以来可能已经发生了变化。
刚刚进行了基准测试,截至 .NET 4,设置 char[] 的成员大约比 StringBuilder 快四倍。但是,两者都可以执行超过200百万个赋值操作,因此在实践中很少有影响。
char[] 读取要稍快一些(对于我的测试代码而言增加了25%),而从 string 读取则略慢。另一方面,从 StringBuilder 读取则更慢(3倍),比从 char[] 读取要慢。
在所有基准测试中,我忽略了其他代码的开销。这意味着我的测试有点低估了差异。
我的结论是,虽然 char[] 比其他选项更快,但只有在每秒超过数百兆字节时才会有影响。
//Write StringBuilder
StringBuilder sb = new StringBuilder();
sb.Length = 256;
for(int i=0; i<1000000000; i++)
{
    int j = i&255;
    sb[j] = 'A';
}

//Write char[]
char[] cs = new char[256];
for(int i=0; i<1000000000; i++)
{
    int j = i&255;
    cs[j] = 'A';
}

// Read string
string s = new String('A',256);
int sum = 0;
for(int i=0; i<1000000000; i++)
{
    int j = i&255;
    sum += s[j];
}

//Read char[]
char[] s = new String('A',256).ToCharArray();
int sum = 0;
for(int i=0; i<1000000000; i++)
{
    int j = i&255;
    sum += s[j];
}

//Read StringBuilder
StringBuilder s= new StringBuilder(new String('A',256));
int sum = 0;
for(int i=0; i<1000000000; i++)
{
    int j = i&255;
    sum += s[j];
}

(是的,我知道我的基准测试代码不是很好,但我认为这并没有太大的影响。)


所有字符串都是内部化的,因此在内存方面使用字符串可以获得性能提升。 - koumides
@koumides 只有字符串字面量和显式使用 interned 的字符串才会被 interned。 - CodesInChaos

5

使用字符数组而非字符串的优点在于你可以直接修改字符数组;在C#中,字符串是不可变的,因此任何更改都会在堆上创建一个新对象,其中包含字符串的更改版本。在字符数组中,你可以进行大量的更改而无需在堆上分配任何内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接