about the string Class and the StringBuilder class

T

Tony Johansson

Hello!

I read in a book and here is a question and the answer that I'm not
satisfied with.
When should you use the StringBuilder class instead of the String class.
1.When building a string from shorter strings.
2.When working with text data longer than 256 bytes.
3.When you want to search and replace the contents of a string
4.When a string is a value type.

The answer that I would choose would be 3 because string object is immutable
so
here is it an advantage to use the StringBuilder class but
according to the book is the right answer 1.

But if you build a string from shorter strings you don't have to use a
StringBuilder class as
string s = "This" + "is" + "a" + "Test";

I can accept numer 1 if they mean this.
string s;
s += "This";
s += "is";
s += "a";
s += "Test";

But it is somewhat unclear what they mean when they say building a string
from shorter strings.

Can somebody give a comment how the book can say that the right answer is
number 1

//Tony
 
B

Brian Gideon

Hello!

I read in a book and here is a question and the answer that I'm not
satisfied with.
When should you use the StringBuilder class instead of the String class.
1.When building a string from shorter strings.
2.When working with text data longer than 256 bytes.
3.When you want to search and replace the contents of a string
4.When a string is a value type.

The answer that I would choose would be 3 because string object is immutable
so
here is it an advantage to use the StringBuilder class but
according to the book is the right answer 1.

But if you build a string from shorter strings you don't have to use a
StringBuilder class as
string s = "This" + "is" + "a" + "Test";

I can accept numer 1 if they mean this.
string s;
s += "This";
s += "is";
s += "a";
s += "Test";

But it is somewhat unclear what they mean when they say building a string
from shorter strings.

Can somebody give a comment how the book can say that the right answer is
number 1

//Tony

The book must have been referring to concatentation. StringBuilder
will be more efficient in that scenario because it uses techniques
that require fewer copy operations. See http://pobox.com/~skeet/csharp/stringbuilder.html
for more information.
 
B

Brian Gideon

The book must have been referring to concatentation.  StringBuilder
will be more efficient in that scenario because it uses techniques
that require fewer copy operations.  Seehttp://pobox.com/~skeet/csharp/stringbuilder.html
for more information.

Oh, by the way, I should point out that you're example is unique in
that the concatenation will occur at compile time since the individual
strings are constant. In that respect the StringBuilder would not
perform any better.
 
I

Ignacio Machin ( .NET/ C# MVP )

Hello!

I read in a book and here is a question and the answer that I'm not
satisfied with.
When should you use the StringBuilder class instead of the String class.
1.When building a string from shorter strings.
2.When working with text data longer than 256 bytes.
3.When you want to search and replace the contents of a string
4.When a string is a value type.

The answer that I would choose would be 3 because string object is immutable
so
here is it an advantage to use the StringBuilder class but
according to the book is the right answer 1.

But if you build a string from shorter strings you don't have to use a
StringBuilder class as
string s = "This" + "is" + "a" + "Test";

I can accept numer 1 if they mean this.
string s;
s += "This";
s += "is";
s += "a";
s += "Test";

But it is somewhat unclear what they mean when they say building a string
from shorter strings.

Can somebody give a comment how the book can say that the right answer is
number 1

The best answer is the 1.
I think that you will understand better why not is 3.
For example. if you want to replace the string "a" for "A" all you
have to do is call string.Replace (which assure you it will use the
most appropriated algorithm).

The example you provide of contatenation is not the best one. The
compiler will contatenate all the strings in only one @ compile time.
But the idea remains that each concatenation will generate one string.
so you end with a lot of temporaries strnigs that have no use. That
why is better to use StrngBuilder
 
K

Kyle

Hi,

Let say I put them into boxes (memory block) to illustrate the activities
involved.

Example 1:

string s = "This" + "is" + "a" + "Test";

| s | |
| s | "This" |
| s | "This" | "is" |
| s | "This" | "is" | "a" |
| s | "This" | "is" | "a" | "Test" |



Example 2:

string s;
s += "This";
s += "is";
s += "a";
s += "Test";

| s | |
| s | "This" |
| s | "This" | "is" |
| s | "This" | "is" | "a" |
| s | "This" | "is" | "a" | "Test" |



Example 3:

StringBuilder s = new StringBuilder();
s.Append("This");
s.Append("is");
s.Append("a");
s.Append("Test");

| s | |
| s | "This" |
| s | "is" |
| s | "a" |
| s | "Test" |



* NOTE 1: Allocating new memory block is a very excessive activity.

* NOTE 2: Also consider that the reserved memory block only released during
the destructor/garbage collector decided to clear it off.
 
J

Jon Skeet [C# MVP]

OD said:
The best is to write a little test project. Test each solution in a big
loop and display time and CLR memory before and after. You'll be
surprised.

The academic solution is of course "use a stringbuilder".
But the reality is a bit different.. Strings are allocated in
generation 0, so mostly in the cpu cache. Short time living strings are
then allocated very quickly and are destroyed very quickly too.
A stringbuilder is a long life object compare to multiple little short
living strings, and when its buffer is full it reallocates it with a
bigger size.

The StringBuilder will only be a "long life" object if it's used as
such - which it isn't very often, in my experience.
As the objet is living a bit longer it can be pushed in generation 1
where it will be destroyed later than in generation 0 (as short living
strings)...

Again, only if it actually lives longer. If enough memory is required
during the concatenation to force a GC to push the StringBuilder into
gen1, then the same memory pressure would have pushed one of the
temporary strings into gen1 when using string concatenation too.
So, if it is very simple to find good samples that show where
StringBuilder is, with no doubt, the best solution, there are plenty of
real situations where the StringBuilder will not be the best solution.
concatenation of short living strings is often better (more often lot
of people is thinking).

Extreme cases are easy to understand, but extreme cases are also less
common in daily development... So don't be too much fool by the
"stringbuilder effiency myth".

There are certainly myths around this topic (as I mention in my
article) but your reasoning above about GC generations just doesn't
hold water in my view. Note that by using StringBuilder you usually (in
typical realistic cases for StringBuilder) use less memory than by
concatenation anyway, so the GC is less likely to *need* to push
anything up to gen1.
 
J

Jon Skeet [C# MVP]

OD said:
I'm sure you tested string vs SB, and you saw, like me, that things are
not as simple as saying "SB is ever the best solution". That's only
what I mean.

Which is why I have the caveats at the bottom of this page:
http://pobox.com/~skeet/csharp/stringbuilder.html
And, of course, I'm not saying that SB is useless and must not be used!
I'm just saying that more than often a "normal" code is just on the
edge, an area where deciding than SB is "certainly" the best solution
is not as obvious as it seems.

But the logic you used for that was flawed. I think it's entirely
reasonable to use StringBuilder for every case where you've got a loop
and are building up a string. Where it's slower, it'll only be very
marginally slower - but where it's faster, it might be very much
faster.
And what I'm trying to explain is "do not follow the 'pensée
unique'(*)" and test by yourself to see where and when SB is really
best than string concatenation.

(*) can be translated by "single thought".

Well, I think the rules of thumb at the bottom of the page linked above
are quite reasonable - you don't need everyone testing their individual
situation every time they need to build a string in a loop.

Beyond that, I was mostly rebutting your flawed logic about the GC and
how StringBuilders end up being more expensive because of being pushed
to gen1.
 
J

Jon Skeet [C# MVP]

OD said:
it's not flawed. You must say "I don't believe it".

I can say more than that - I can give a logical technical reason why I
don't believe it. Indeed, I gave that reason before, and I've given it
again below.
It's just a believing problem, not a technical one.

I gave a rebuttal in the previous post. If at some point a
StringBuilder gets pushed into gen1, that must be because a garbage
collection occurred, almost certainly due to memory pressure.

If that happens, using repeated string concatenation would *also* have
forced a garbage collection (as repeated string concatenation is less
efficient in terms of memory than using StringBuilder in almost every
conceivable scenario). At that point, whatever string was currently
"active" would be pushed to gen1 - so you'd still have an object in
gen1 either way. You're less likely to get anything in gen1 with
StringBuilder as you're less likely to provoke the GC.
Or that means you're saying "i'm the expert, not you". Perhaps it's
true, perhaps not...

No, I wouldn't say that. Appealing to authority is an unsatisfying
approach.
As I know what I say, I can just ask you to test a little bit more and
you'll see.

And I can ask you to answer the logic of my rebuttal :)
 
J

Jon Skeet [C# MVP]

OD said:
Well... time to stop splitting hair.

I'm not splitting hairs. You suggested a way in which StringBuilder
could be disadvantageous, and I pointed out the flaw in your logic.
Like you I wrote tests, but I saw something you did not see.

You also interpreted your data. I *suspect* it's the interpretation
which is flawed, but without knowing the data it's hard to say. I'd be
interested to hear more though.
I don't want to go farther, this is becoming boring for other readers I
presume.

I wouldn't like to say either way - but I'm certainly interested in
pursuing it further.

It's a C# newsgroup so it will certainly be a bit too philsophical to
explain how something that seems to be logical can be false ... how a
beautiful brain construction can be wrong when it faces the facts :)

Again, if you could show your data I'd be interested to see if there's
an alternative explanation. Having reviewed my logic, it still seems
sound to me.
 
M

Marc Gravell

I don't want to go farther, this is becoming boring for other readers I
I wouldn't like to say either way - but I'm certainly interested in
pursuing it further.

Seconded; if there is a bona fide way in which concatenation can avoid
gen1 when the equivalent using StringBuilder wouldn't, I'd be very
interested in seeing it... but just stating "test a little bit more
and you'll see" isn't very convincing. At the point GC occurs, the
only interesting objects (relevant to the discussion) are the
StringBuilder and the current accumulated (cancatenated) string.

There is only one *very* edge case I can think of here, which is when
the doubling approach of StringBuilder extension /itself/ forces GC,
but in any interesting case the StringBuilder can only have consumed
less memory than concatenation: with StringBuilder, there are three
cases:

1: enough space capacity - new data appended without allocating any
extra memory
2: not enough space, but doubling would give enough - new buffer
allocated (twice size) and new data appended
3: not enough space, doubling also not enough - new buffer allocated
to new required size and data appended

(case 2 leaves spare capacity allowing for case 1 at the next step,
assuming fairly linear growth)

With string concatenation, you are essentially using case 3 each time,
so *every* concatenation has to allocate a new buffer.

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top