如果要进一步修改字符串,则返回 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)。
更新
System.String 是一个类,这意味着它是一个引用类型(而不是值类型),所以“string foo;” 本质上是一个指针。(当您将字符串传递给方法时,它传递的是指针,而不是副本。) System.String 在 mscorlib 内部是可变的,但在它外部是不可变的,这就是 StringBuilder 操作字符串的方式。
因此,当调用 ToString() 时,它通过引用返回其内部字符串对象。此时您无法修改它,因为您的代码不在 mscorlib 中。通过将 m_currentThread 字段设置为零,StringBuilder 上的任何进一步操作都将导致它复制字符串对象,以便可以修改它而不修改它在 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”。
这是否澄清了整个返回/参考的事情?