More StringBuilder advice

Published 15 December 03 01:32 PM | ricom 

I first wrote about this here, but I've since received several requests for more prescriptive advice on the subject.  Again you can never be sure without understanding the exact usage pattern because the results really do vary widely but here's some general guidelines that may be useful.

The choice (String vs. StringBuilder) usually turns not on whether the strings are known at compile time or not, but rather on whether the number of appends is known.  This is especially true if you can't really be sure of the sizes in advance either (i.e. they might vary).

e.g.
 
if your pattern looks like:
x = f1(...) + f2(...) + f3(...) + f4(...)
 
that's one concat and it's zippy, StringBuilder probably won't help.
 
if your pattern looks like:
if (...) x += f1(...)
if (...) x += f2(...)
if (...) x += f3(...)
if (...) x += f4(...)
 
then you probably want StringBuilder.
 
Things like generating SQL on the fly for a query probably want StringBuilder, things like making an absolute file path from components probably don't (unless those components could be put into a buffer that's part of some bigger operation, thereby saving temporary strings).
 
Don't underestimate the value of this pattern:
StringBuilder sb;
 
if (...) AppendF1(sb,...)
if (...) AppendF2(sb,...)
if (...) AppendF3(sb,...)
if (...) AppendF4(sb,...)
 
If you pass in the buffer, then the f1 through f4 append functions might not ever need to make temporary string parts, they can stream into the buffer.  And it recurses well.  For large scale string assembly (like making SQL statements on the fly) I find the last pattern very useful.  Reusing the same buffer can be much better than:
 
if (...) sb.Append(f1(...))
if (...) sb.Append(f2(...))
if (...) sb.Append(f3(...))
if (...) sb.Append(f4(...))
Please remember to ignore my advice when you have a thoughtful reason to do so :)
 
Filed under:

Comments

# Nicko said on December 16, 2003 4:19 AM:
I often find that passing a TextWriter to child functions can be more benificial that just passing a StringBuilder.

If you pass in a StringWriter the effect is the same as passing a StringBuilder.

If you decide that one time you want the output to go to a file rather than into a string you can do that without creating a temporary string.
# Luke Hutteman said on December 16, 2003 3:17 PM:
what about a construct like:

x = (... ? f1(...) : "")
+ (... ? f2(...) : "")
+ (... ? f3(...) : "")
+ (... ? f4(...) : "");

would that still use a single concat or would the ternary expressions screw things up to where a StringBuilder would be faster?
# Rico Mariani said on December 16, 2003 4:27 PM:
Always check the generated code to be sure because even "experts" like me are surprised sometimes, however in this particular case I believe you will still get concat.
# Jim Argeropoulos said on December 19, 2003 10:31 AM:
I often choose string.Format() over chaining strings with the plus operator. Any comments on this?

I think you are going to tell me that it amounts to a cat, but?

Thanks
Jim

Oh, yeah. One more thing. Reading between the lines, I would guess that a string builder should not be appended to after calling ToString(). Is that a fair statement?
# Rico Mariani said on December 19, 2003 12:49 PM:
String.Format takes the various arguments, builds them into an object array, creates an empty StringBuilder and then passes them along to the StringBuilder.FormatAppend services.

That will be quite a bit more costly than just the straight append in the easy cases. But it does offer advantages such as localizability and so forth. It's certainly not a plain cat. You can see this happening if you trace it all with CLRProfiler which I highly recommend.

Your reading between the lines is quite correct. It's not such a good idea to use a StringBuilder after you've extracted the string because the StringBuilder sort of falls on a sword on your behalf when you take the string out -- the internal buffer is converted into an immutable string in place. Further appends basically start from scratch.
# Tyson Brown said on February 18, 2004 8:43 AM:
Quick question on the pattern above: Is is true that VB.NET doesn't have true ByRefs?

I had read a while back that VB.NET still makes a copy of object, then another copy of the object to return..
# Mungo Knotwise of Michel Delving said on February 22, 2004 7:29 PM:
# The Diffracted Developer @ Home said on March 20, 2004 1:23 PM:
# Kingsley Tagbo said on March 22, 2004 3:20 PM:
Is there another reason for passing a StringBuilder to a StringWriter's constructor apart from the fact that you can manipulate the underlying string in the StringBuilder after the StringWriter is closed :

//E.G.

StringBuilder sb = new StringBuilder();
StringWriter writer = new StringWriter(sb);
Dataset.WriteXml(writer, XmlWriteMode.WriteSchema);
writer.Close();

Return sb.ToString();

# Bob Gladon said on May 24, 2005 3:41 AM:
# 杨其明 said on February 3, 2007 11:16 PM:

1、String创建一个不可改变的对象,StringBuilder创建一个可以改变的对象。stringstr1=

# David Cumps » String Concatenation vs Memory Allocation said on September 16, 2007 1:34 PM:

PingBack from http://blog.cumps.be/string-concatenation-vs-memory-allocation/

# new2008 said on January 15, 2008 2:39 AM:

String和StringBuilder

1、String创建一个不可改变的对象,StringBuilder创建一个可以改变的对象。

stringstr1=

# StringBuilder | keyongtech said on January 21, 2009 9:58 PM:

PingBack from http://www.keyongtech.com/671177-stringbuilder

New Comments to this post are disabled

Search

This Blog

Syndication

Page view tracker