2009-02-02 49 views
6

StringBuilder作为一个快速的字符串操作工具而不仅仅是串联字符串。不管这是否是真的,我仍然想知道StringBuilder操作的结果以及它们产生的字符串。StringBuilder字符串是不可变的吗?

Reflector中的一个简短短语显示StringBuilder.ToString()并不总是返回一个副本,有时它似乎返回内部字符串的一个实例。它似乎也使用一些内部函数来操纵内部字符串。

那么,如果我这样做,我会得到什么?

string s = "Yo Ho Ho"; 
StringBuilder sb = new StringBuilder(s); 
string newString = sb.ToString(); 
sb.Append(" and a bottle of rum."); 
string newNewString = sb.ToString(); 

是newString和newNewString不同的字符串实例还是一样的?我试图通过反射器了解这一点,而我只是不完全了解所有事情。

这段代码如何?

StringBuilder sb = new StringBuilder("Foo\n"); 
StringReader sr = new StringReader(sb.ToString()); 
string s = sr.ReadLine(); 
sb.Append("Bar\n"); 
s = sr.ReadLine(); 

最后一条语句是否返回null或“Bar”?如果它返回一个或另一个,这是定义的还是未定义的行为?换句话说,我可以依靠它吗?

该文档在这个主题上非常简洁,我不愿意依赖于观察到的行为超过规范。

+0

请注意,自问题被回答后,StringBuilder的实现已经发生了变化。 – mayu 2016-02-16 13:13:43

回答

10

在mscorlib之外,System.String的任何实例都是不可变的,句点。

StringBuilder在内部对字符串做了一些有趣的操作,但是在一天结束时它不会返回一个字符串给你,然后以你的代码可见的方式对它进行变异。

至于对StringBuilder.ToString()的后续调用是否返回具有相同值的String或具有相同值的不同String的同一实例,这与实现相关,您不应该依赖此行为。

+0

是的,实验已经证明这是真实的,但是用Reflector在内部进行探测没有显示明显的原因。它似乎在每次调用中都返回对内部字符串的引用,因此我对字符串是否可能发生变化感到困惑。 – 2009-02-02 06:30:42

+0

@Mystere,StringBuilder的实现起初有点让人望而生畏。直到我读你的问题,并开始探索我没有意识到他们做线程级缓存。我打算今晚(或明天)稍后再观看。但是你可以相信所产生的字符串是不可改变的 – JaredPar 2009-02-02 06:34:02

4

newStringnewNewString是不同的字符串实例。

尽管ToString()返回当前字符串,它将清除其当前线程变量。这意味着下次您追加时,它会在追加之前获取当前字符串的副本。

我不完全确保你在你的第二个问题得到什么,但s将是无效的:如果在一个文件中的最后字符是上一行行终止字符(S),该行是而不是被认为在这些字符和文件结尾之间有一个空行。之前读取的字符串对此没有任何影响。

+0

啊..你向我解释了这个谜。清除线程变量是导致附加副本的原因,简单但不明显。我的第二个问题是关于存储在StringReader中的引用的可变性问题的变体。 – 2009-02-02 06:41:42

2

这个类的全部目的是使字符串可变,所以它实际上是。我相信(但不是很确定)它只会返回与该对象完全没有关系的字符串。所以经过

String s_old = "Foo"; 
StringBuilder sb = new StringBuilder(s_old); 
String s_new = sb.ToString(); 

s_old会和s_new一样,但不会在任何其他情况下。

我应该注意到,对于Java编译器自动将多个字符串添加到使用StringBuilder(或类似的,但更快的StringBuffer)类的操作中,我会非常惊讶。NET编译器也不会执行此转换。

3

newStringnewNewString 不同string实例或 一样的吗?我试图找出通过反射器 ,我只是不知道一切 。

他们是不同的string实例:newString是 “Yo Ho Ho” 和newNewString为 “Yo Ho Ho and a bottle of rum.”。 strings是不可变的,并且当您调用StringBuilder.ToString()时,此方法返回一个不可变的string,它表示当前的状态。

会的最后一条语句返回null或 “Bar”?并且如果它返回一个或其他 其他,这是定义还是未定义 行为?换句话说,我可以依靠 吗?

它将返回nullStringReader正在处理您在构造函数中传递给它的不可变的string,因此它不受您对StringBuilder所做的任何操作的影响。