Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
字符串和StringBuilder的性能注意事项-C#_C#_String - Fatal编程技术网

字符串和StringBuilder的性能注意事项-C#

字符串和StringBuilder的性能注意事项-C#,c#,string,C#,String,全部, 对于字符串string s=“abcd”,string w=s.SubString(2)是否在内部返回新分配的字符串对象,即string w=new string(“cd”) 对于StringBuilder,在追加字符串值时,如果需要增加StringBuilder的大小,是将所有内容复制到新的内存位置,还是将指向每个先前字符串值的指针重新分配到新位置?string是不可变的,因此任何“更改”字符串的操作,实际上将返回一个新字符串。这包括子字符串和对字符串的所有其他操作,包括那些不改变长度

全部,

对于字符串
string s=“abcd”
string w=s.SubString(2)
是否在内部返回新分配的字符串对象,即
string w=new string(“cd”)


对于StringBuilder,在追加字符串值时,如果需要增加StringBuilder的大小,是将所有内容复制到新的内存位置,还是将指向每个先前字符串值的指针重新分配到新位置?

string
是不可变的,因此任何“更改”字符串的操作,实际上将返回一个
新字符串
。这包括
子字符串
和对
字符串
的所有其他操作,包括那些不改变长度的操作(如ToLower()或类似操作)


StringBuilder
内部包含一个字符块的链接列表。当数据块需要增长时,会分配一个新的数据块,并将其插入列表的末尾,然后将数据复制到此处。换句话说,整个StringBuilder缓冲区不会在追加时复制,只会复制正在追加的数据。我在Framework 4参考源中对此进行了双重检查。

对于字符串s=“abcd”,字符串w=s.SubString(2)是否返回新分配的字符串对象?

对于StringBuilder,在追加字符串值时,如果需要增加StringBuilder的大小,是否将所有内容复制到新的内存位置?


字符串大小的任何更改都会导致新字符串

字符串是不可变的对象,因此每次必须进行更改时,都会创建该字符串的新实例。substring方法不会更改原始字符串的值


注意。

如果要对字符串进行大量编辑,最好通过StringBuilder进行编辑

发件人:

对于对字符串值进行多次更改的操作,可以使用StringBuilder类而不是String类。与String类的实例不同,StringBuilder对象是可变的;从字符串中连接、追加或删除子字符串时,操作将在单个字符串上执行


字符串StringBuilder之间的差异是一个重要的概念,当应用程序必须处理大量字符串的编辑时,这一概念会产生差异

字符串

String对象是UTF-16代码单元的集合,由属于系统命名空间的System.Char对象表示。由于此对象的值是只读的,因此整个对象字符串定义为不可变。内存中字符串对象的最大大小为2GB,约为10亿个字符

不可变的 不可变意味着每次使用System.String的方法时,都会在内存中创建一个新的sting对象,这会为新对象分配新的空间

例如: 通过使用字符串连接运算符+=显示名为test的字符串变量的值发生了更改。实际上,它创建了一个新的String对象,该对象的值和地址与原始对象不同,并将其分配给测试变量

string test;
test += "red"; // a new object string is created
test += "coding"; // a new object string is created
test += "planet"; // a new object string is created
StringBuilder

StringBuilder是一个动态对象,它属于System.Text命名空间,允许修改它封装的字符串中的字符数,这个特性称为可变性

易变性 为了能够追加、删除、替换或插入字符,StringBuilder维护了一个缓冲区,以适应字符串的扩展。如果有可用空间,则将新数据附加到缓冲区;否则,将分配一个新的、更大的缓冲区,将原始缓冲区中的数据复制到新缓冲区,然后将新数据追加到新缓冲区

StringBuilder sb = new StringBuilder("");
sb.Append("red");
sb.Append("blue");
sb.Append("green ");
string colors = sb.ToString();
性能

为了帮助您更好地理解String和StringBuilder之间的性能差异,我创建了以下示例:

Stopwatch timer = new Stopwatch();
string str = string.Empty;
timer.Start();
for (int i = 0; i < 10000; i++) {
    str += i.ToString();
}
timer.Stop();
Console.WriteLine("String : {0}", timer.Elapsed);

timer.Restart();

StringBuilder sbr = new StringBuilder(string.Empty);
for (int i = 0; i < 10000; i++) {
    sbr.Append(i.ToString());
}
timer.Stop();
Console.WriteLine("StringBuilder : {0}", timer.Elapsed);

谢谢你的回复。实际上,我的问题更多的是,如果String.Substring()返回
新字符串(XXXX)
,或者只返回
“XXXX”
。我得到了答案,虽然它将永远是一个新的对象。事实上(只要不涉及字符串常量或插入的字符串),谈论返回“
新字符串(XXXX)
”XXXX之间的区别就没有什么意义“
。你能告诉我你所说的参考资料吗?谢谢你的链接。但我认为它完全是从原始字符串数组复制到新的字符串数组。在String.cs中,方法GetStringForStringBuilder(),它获取原始字符串及其所需的长度
wstrcpy(dest,src+startIndex,length)其中startIndex为0。我说的对吗?GetStringForStringBuilder()用于从字符串转换到字符串生成器。我刚才说的是StringBuilder内部调整大小操作。谢谢您的回复。实际上,我的问题更多的是,如果String.Substring()返回
新字符串(XXXX)
,或者只返回
“XXXX”
。是的,即使使用方法SubString,堆上也会有一个新对象这些是引用类型,而不是divalore类型,例如变量,例如结构。实际上,当需要更多空间时,所有现有内容都不会复制到新缓冲区。(这是根据Framework4.0参考源检查的)。@driis:MSDN说,
StringBuilder对象维护一个缓冲区以容纳新数据的连接。如果有可用空间,新数据将附加到缓冲区的末尾**否则,将分配一个新的、更大的缓冲区,将原始缓冲区中的数据复制到新缓冲区,然后将新数据追加到新缓冲区**。
这是否意味着将所有现有数据复制到新缓冲区?
Output
String : 00:00:00.0706661
StringBuilder : 00:00:00.0012373