如果要进一步修改字符串,则返回 StringBuilder,否则返回字符串。这是一个API问题。
关于效率。由于这是一个模糊/笼统的问题,没有任何具体细节,所以我认为可变与不可变比性能更重要。可变性是让 API 返回可修改对象的 API 问题。字符串长度与此无关。
就是这样说的。如果您使用 Reflector 查看 StringBuilder.ToString:
public override string ToString()
{
string stringValue = this.m_StringValue;
if (this.m_currentThread != Thread.InternalGetCurrentThread())
{
return string.InternalCopy(stringValue);
}
if ((2 * stringValue.Length) < stringValue.ArrayLength)
{
return string.InternalCopy(stringValue);
}
stringValue.ClearPostNullChar();
this.m_currentThread = IntPtr.Zero;
return stringValue;
}
你可以看到它可能会制作一个副本,但如果你用 StringBuilder 修改它,那么它就会制作一个副本(这就是我可以告诉 m_currentThread 的点是因为 Append 会检查它,如果它与当前线程不匹配,则会复制它) 。
我想最终的结果是,如果您不修改 StringBuilder,那么您就不会复制字符串,并且长度与效率无关(除非您遇到第二个 if)。
UPDATE
System.String 是一个类,这意味着它是一个引用类型(而不是值类型),因此“string foo;”本质上是一个指针。 (当您将字符串传递给方法时,它传递的是指针,而不是副本。)System.String 在 mscorlib 内部是可变的,但在其外部是不可变的,这就是 StringBuilder 操作字符串的方式。
因此,当调用 ToString() 时,它会通过引用返回其内部字符串对象。此时您无法修改它,因为您的代码不在 mscorlib 中。通过将 m_currentThread 字段设置为零,然后对 StringBuilder 的任何进一步操作都将导致它复制字符串对象,以便可以对其进行修改and不修改 ToString() 中返回的字符串对象。考虑一下:
StringBuilder sb = new StringBuilder();
sb.Append("Hello ");
string foo = sb.ToString();
sb.Append("World");
string bar = sb.ToString();
如果 StringBuilder 没有进行复制,那么最后 foo 将是“Hello World”,因为 StringBuilder 修改了它。但既然它确实复制了,那么 foo 仍然只是“Hello”,而 bar 是“Hello World”。
这是否澄清了整个返回/参考的事情?