C# String 或 StringBuilder 返回值?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/834479/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
String or StringBuilder return values?
提问by John Bubriski
If I am building a string using a StringBuilder object in a method, would it make sense to:
如果我在方法中使用 StringBuilder 对象构建字符串,是否有意义:
Return the StringBuilder object, and let the calling code call ToString()?
返回 StringBuilder 对象,让调用代码调用 ToString()?
return sb;
OR Return the string by calling ToString() myself.
或 通过自己调用 ToString() 返回字符串。
return sb.ToString();
I guess it make a difference if we're returning small, or large strings. What would be appropriate in each case? Thanks in advance.
我想如果我们返回小字符串或大字符串会有所不同。在每种情况下什么是合适的?提前致谢。
Edit: I don't plan on further modifying the string in the calling code, but good point Colin Burnett.
编辑:我不打算进一步修改调用代码中的字符串,但是 Colin Burnett 是个好主意。
Mainly, is it more efficient to return the StringBuilder object, or the string? Would a reference to the string get returned, or a copy?
主要是,返回 StringBuilder 对象还是字符串更有效?会返回对字符串的引用还是副本?
采纳答案by Colin Burnett
Return the StringBuilder if you're going to further modify the string, otherwise return the string. This is an API question.
如果您要进一步修改字符串,则返回 StringBuilder,否则返回字符串。这是一个 API 问题。
Regarding efficiency. Since this is a vague/general question without any specifics then I think mutable vs. immutable is more important than performance. Mutability is an API issue of letting your API return modifiable objects. String length is irrelevant to this.
关于效率。由于这是一个没有任何细节的模糊/一般性问题,因此我认为可变与不可变比性能更重要。可变性是让您的 API 返回可修改对象的 API 问题。字符串长度与此无关。
That said. If you look at StringBuilder.ToString with 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;
}
You can see it may make a copy but if you modify it with the StringBuilder then it will make a copy then (this is what I can tell the point of m_currentThread is because Append checks this and will copy it if it mismatches the current thread).
您可以看到它可能会创建一个副本,但是如果您使用 StringBuilder 修改它,那么它将创建一个副本(这就是我可以告诉 m_currentThread 的一点是因为 Append 会检查它,如果它与当前线程不匹配,则会复制它) .
I guess the end of this is that if you do not modify the StringBuilder then you do not copy the string and length is irrelevant to efficiency (unless you hit that 2nd if).
我想最后是,如果您不修改 StringBuilder,那么您就不会复制字符串,并且长度与效率无关(除非您达到了第二个 if)。
UPDATE
更新
System.String is a class which means it is a reference type (as opposed to value type) so "string foo;" is essentially a pointer. (When you pass a string into a method it passes the pointer, not a copy.) System.String is mutable inside mscorlib but immutable outside of it which is how StringBuilder can manipulate a string.
System.String 是一个类,这意味着它是一个引用类型(而不是值类型)所以“string foo;” 本质上是一个指针。(当您将字符串传递给方法时,它传递的是指针,而不是副本。) System.String 在 mscorlib 内部是可变的,但在外部是不可变的,这就是 StringBuilder 可以操作字符串的方式。
So when ToString() is called it returns its internal string object by reference. At this point you cannot modify it because your code is not in mscorlib. By setting the m_currentThread field to zero then any further operations on the StringBuilder will cause it to copy the string object so it can be modified andnot modify the string object it returned in ToString(). Consider this:
因此,当调用 ToString() 时,它会通过引用返回其内部字符串对象。此时您无法修改它,因为您的代码不在 mscorlib 中。通过将 m_currentThread 字段设置为零,对 StringBuilder 的任何进一步操作将导致它复制字符串对象,以便可以修改它,而不是修改它在 ToString() 中返回的字符串对象。考虑一下:
StringBuilder sb = new StringBuilder();
sb.Append("Hello ");
string foo = sb.ToString();
sb.Append("World");
string bar = sb.ToString();
If StringBuilder did not make a copy then at the end foo would be "Hello World" because the StringBuilder modified it. But since it did make a copy then foo is still just "Hello " and bar is "Hello World".
如果 StringBuilder 没有制作副本,那么最后 foo 将是“Hello World”,因为 StringBuilder 修改了它。但既然它做了一个副本,那么 foo 仍然只是“Hello”,而 bar 是“Hello World”。
Does that clarify the whole return/reference thing?
这是否澄清了整个返回/引用的事情?
回答by JoshBerke
I don't think performance should be a factor in this question. Either way someone is going to call sb.ToString() so your going to take the hit someplace.
我不认为性能应该是这个问题的一个因素。无论哪种方式,有人都会调用 sb.ToString() 所以你会在某个地方受到打击。
The more important question is what is the intention of the method and the purpose. If this method is part of a builder you might return the string builder. Otherwise I would return a string.
更重要的问题是该方法的意图和目的是什么。如果此方法是构建器的一部分,您可能会返回字符串构建器。否则我会返回一个字符串。
If this is part of a public API I would lean towards returning a string instead of the builder.
如果这是公共 API 的一部分,我会倾向于返回一个字符串而不是构建器。
回答by Nick Allen
I would say the method should return sb.ToString(). If the logic surrounding the creation of the StringBuilder() object should change in the future it makes sense to me that it be changed in the method not in each scenario which calls the method and then goes on to do something else
我会说该方法应该返回 sb.ToString()。如果围绕创建 StringBuilder() 对象的逻辑在未来发生变化,那么对我来说在方法中进行更改是有意义的,而不是在调用该方法然后继续做其他事情的每个场景中
回答by Allen Rice
If you need to append more stuff to the string and use other stringbuilder related functionality, return the stringbuilder. Otherwise if you're just using the string itself, return the string.
如果您需要向字符串附加更多内容并使用其他与字符串构建器相关的功能,请返回字符串构建器。否则,如果您只是使用字符串本身,则返回字符串。
There are other more technical considerations, but thats the highest level concerns.
还有其他更多的技术考虑,但这是最高级别的关注。
回答by kemiller2002
It depends on what you are planning on doing with the output. I would return a string personally. That way if you need to change the method down the road to not use a stringbuilder, you can as you won't be stuck with that as a return value.
这取决于您计划对输出做什么。我会亲自返回一个字符串。这样,如果您需要更改方法以不使用字符串构建器,您可以这样做,因为您不会将其作为返回值。
Upon thinking about it for the moment, the answer is much clearer. The question of asking which should be returned really answers the question. The return object should be a string. The reason is that if you are asking the question, "Is there a reason to return the StringBuilder object when a string will do?" then the answer is no. If there was a reason, then returning string would be out of the question, because the methods and properties of the stringbuilder are needed.
暂时想一想,答案就清楚多了。问哪个应该返回的问题确实回答了这个问题。返回对象应该是一个字符串。原因是,如果您问这个问题,“当字符串可以执行时,是否有理由返回 StringBuilder 对象?” 那么答案是否定的。如果有原因,那么返回字符串将是不可能的,因为需要 stringbuilder 的方法和属性。
回答by Steve Willcock
I think it depends what you are doing with the string once it leaves the method. If you are going to continue appending to it then you might want to consider returning a stringbuilder for greater efficiency. If you are always going to call .ToString() on it then you should do that inside the method for better encapsulation.
我认为这取决于你在离开方法后对字符串做什么。如果您要继续附加到它,那么您可能需要考虑返回一个 stringbuilder 以提高效率。如果您总是要在其上调用 .ToString() ,那么您应该在方法内部执行此操作以获得更好的封装。
回答by LukeH
I would return a string
in almost all situations, especially if the method is part of a public API.
我string
几乎在所有情况下都会返回 a ,特别是如果该方法是公共 API 的一部分。
An exception would be if your method is just one part of a larger, private "builder" process and the calling code will be doing further manipulations. In that case then I'd maybe consider returning a StringBuilder
.
一个例外是,如果您的方法只是更大的私有“构建器”进程的一部分,并且调用代码将进行进一步的操作。在那种情况下,我可能会考虑返回一个StringBuilder
.
回答by Fredrik Leijon
Since your not going to modify it anymore
因为你不会再修改它了
return sb.ToString();
should be most efficient
应该是最有效的
回答by Fredrik Leijon
Return the sb.ToString(). Your method should concentrate on just the thing in hand (In this case build me a string) and not be returned to be further manipulated IMO, you could get into all sorts of problems with it not being disposed.
返回 sb.ToString()。您的方法应该只专注于手头的事情(在这种情况下为我构建一个字符串),而不是返回以进一步操作 IMO,您可能会遇到各种问题,因为它没有被处理。
回答by Michael Meadows
StringBuilder
is an implementation detail of your method. You should return string until it becomes a performance problem, at which point you should explore another pattern (like visitor Pattern) that can help you introduce indirection and protect you from the internal implementation decisions.
StringBuilder
是您的方法的实现细节。您应该返回字符串,直到它成为一个性能问题,此时您应该探索另一种模式(如访问者模式),它可以帮助您引入间接并保护您免受内部实现决策的影响。
Strings are always stored in the heap, so you will have a reference returned if the return type is string. You can't count, however, on two identical strings to have identical references. In general, it's safe to think of a string as if it were a value type even though it is actually a reference type.
字符串总是存储在堆中,因此如果返回类型是字符串,您将返回一个引用。但是,您不能指望两个相同的字符串具有相同的引用。通常,将字符串视为值类型是安全的,即使它实际上是引用类型。