return sb;
或者通过调用 ToString() 方法自己返回字符串。
return sb.ToString();
我猜这会因为返回的字符串大小不同而有所差别。在每种情况下,什么是更合适的?谢谢。
编辑: 我不打算在调用代码中进一步修改字符串,但Colin Burnett提出了一个好观点。
主要的问题是:返回StringBuilder对象还是字符串更有效率?字符串的引用将被返回还是拷贝?
return sb;
或者通过调用 ToString() 方法自己返回字符串。
return sb.ToString();
我猜这会因为返回的字符串大小不同而有所差别。在每种情况下,什么是更合适的?谢谢。
编辑: 我不打算在调用代码中进一步修改字符串,但Colin Burnett提出了一个好观点。
主要的问题是:返回StringBuilder对象还是字符串更有效率?字符串的引用将被返回还是拷贝?
如果您要进一步修改字符串,则返回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;”本质上是一个指针。(当你将一个字符串传递给一个方法时,它会传递指针而不是副本。)mscorlib中的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"。我认为该方法应返回sb.ToString()。如果以后围绕StringBuilder()对象的创建的逻辑发生改变,那么我觉得应该在该方法中更改,而不是在每个调用该方法并继续执行其他操作的场景中更改。
StringBuilder
是您方法的实现细节。在性能成为问题之前,应返回字符串,此时您应该探索另一种模式(如访问者模式),以帮助您引入间接性并保护您免受内部实现决策的影响。
字符串始终存储在堆中,因此如果返回类型为字符串,则将返回引用。但是,您不能指望两个相同的字符串具有相同的引用。通常情况下,尽管它实际上是引用类型,但可以安全地将字符串视为值类型。
既然你不再需要修改它了
return sb.ToString();
应该是最有效的
这取决于您打算如何处理输出。我个人会返回一个字符串。这样,如果您需要在将来更改方法以不使用stringbuilder,则可以这样做,因为您不会被困在返回值中。
经过一段时间的思考,答案变得更加清晰。询问应该返回哪个对象的问题真正回答了这个问题。返回的对象应该是一个字符串。原因是,如果您问自己“是否有理由返回StringBuilder对象,而不是使用字符串?”那么答案是否定的。如果有理由,则返回字符串就不可能了,因为需要使用stringbuilder的方法和属性。
在几乎所有情况下,尤其是当方法是公共 API 的一部分时,我会返回一个 string
。
唯一的例外是,如果您的方法只是更大的私有“构建器”过程中的一部分,并且调用代码将进行进一步操作。在这种情况下,我可能会考虑返回一个 StringBuilder
。
返回 sb.ToString()。在这个案例中,你的方法应该集中精力于手头的任务(构建字符串),而不是被返回以进一步操作。据我看来,你可能会遇到各种问题,比如没有被释放。
如果您需要向字符串附加更多内容并使用其他stringbuilder相关功能,请返回stringbuilder。 否则,如果您只是使用字符串本身,请返回该字符串。
还有其他更技术上的考虑,但这是最高级别的问题。