C# strings

  • Thread starter Thread starter Trevor
  • Start date Start date
T

Trevor

I have a couple of questions regarding C# strings.

1) Sometimes I see a string in someone else's code like:

string foo = @"bar";

What does the '@' do for you?


2) Is there a performance loss if I start concatenating strings together
with the + operator ? In Java, they discouraged code like this:

string command = "CMD " + var1 + " " + var2;

The reason is because of all of the temporary String objects that get
created in the meantime. The solution is to use a StringBuffer like so:

StringBuffer command = new StringBuffer("CMD ");
command.append(var1);
command.append(' ');
command.append(var2);
System.out.println(command.toString());

This is less expensive than the above code because String objects are not
being created left & right. Does C# have the same problem? I noticed that
C# has a StringBuilder class which is just like the Java StringBuffer class.
Should I use StringBuffer in cases like the above where I need to
concatenate multiple strings to one string?
 
Hi Trevor,

Please see response in-line.

Joe
--
http://www.csharp-station.com

Trevor said:
1) Sometimes I see a string in someone else's code like:

string foo = @"bar";

What does the '@' do for you?

That's a verbatim string literal, which preserves characters between the
double quotes. One of its uses is when you want to make file paths more
readable. For example, in a normal string, you would escape the path
separator like this:

"c:\\MyDir\\MySubDir\\MyFile.cs"

Instead, you can do this:

@"c:\MyDir\MySubDir\MyFile.cs"

Also, you can sometimes do something like this:

@"
This is some text that I
want to show on the
console with line feeds
"
Instead of:

"This is some text that I\n want to show on the\n console with line feeds"

or something else less readable.
2) Is there a performance loss if I start concatenating strings together
with the + operator ? In Java, they discouraged code like this:

string command = "CMD " + var1 + " " + var2;

Yes, there is a performance penalty with these concatenations because of new
string objects being created on each concatenation. The string type is
immutable.
Should I use StringBuffer in cases like the above where I need to
concatenate multiple strings to one string?

You should use the StringBuilder. I use a rule-of-thumb that when I have 4
or more concatenations, I will use a StringBuilder instead.
 
Trevor,

See inline.

Trevor said:
I have a couple of questions regarding C# strings.

1) Sometimes I see a string in someone else's code like:

string foo = @"bar";

What does the '@' do for you?

The amperstand means to take the string as a literal, and not interpret
escape codes. For example, when working with paths, you have to use "\"
twice for each path separator, because "\" needs to be escaped, like so:

"c:\\temp"

However, with a string literal, there are no escape characters, so you
don't have to worry. You can write this:

@"c:\temp"
2) Is there a performance loss if I start concatenating strings together
with the + operator ? In Java, they discouraged code like this:

string command = "CMD " + var1 + " " + var2;

The reason is because of all of the temporary String objects that get
created in the meantime. The solution is to use a StringBuffer like so:

StringBuffer command = new StringBuffer("CMD ");
command.append(var1);
command.append(' ');
command.append(var2);
System.out.println(command.toString());

This is less expensive than the above code because String objects are not
being created left & right. Does C# have the same problem? I noticed that
C# has a StringBuilder class which is just like the Java StringBuffer class.
Should I use StringBuffer in cases like the above where I need to
concatenate multiple strings to one string?

Generally speaking, if you have a lot of string manipulation to do, then
you should use a StringBuilder instance to do it. It will be faster than
just concatenating strings. It should be noted that the following line:

string command = "CMD " + var1 + " " + var2;

Is actually going to be compiled into:

string command = String.Concat("CMD ", var1, " ", var2);

Underneath the covers, Concat uses a StringBuilder instance to do its
work. Also, it should be noted that the compiler treats the concatenation
of two string literals as a single instance. In other words:

"Hello " + "there"

Is compiled into:

"Hello there"

Hope this helps.
[/QUOTE]
 
Trevor said:
I have a couple of questions regarding C# strings.

1) Sometimes I see a string in someone else's code like:

string foo = @"bar";

What does the '@' do for you?


2) Is there a performance loss if I start concatenating strings together
with the + operator ? In Java, they discouraged code like this:

string command = "CMD " + var1 + " " + var2;

Hello Trevor,

#2: C# is much the same, and the string builder class is provided for that.
I think though that if you are just concatenating a couple of variables, the
performance hit isn't so hard. It's building large strings where string
builder is handy. There's been lots of discussion on this topic, but for
myself, I use string builder if I'm concatenating more than say 10 items.

#1: The @ sign causes the compiler to treat the string as it is, and not
look for escape characters and whatnot, or something like that. I only know
that if I want to hardcode a folder and filename, or something like that, I
have to use the @"[string]" or it doesn't work properly. Surely someone else
will give a more definitive answer. Looking forward to that myself.

Eric
 
@ says "This is my string, including any special characters". In other
cases, you have to include special characters. For example, to have the
string "10\10" you would write either as "10\\10" or @"10\10".

--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA

**********************************************************************
Think Outside the Box!
**********************************************************************
 
Trevor said:
1) Sometimes I see a string in someone else's code like:

string foo = @"bar";

What does the '@' do for you?

In that case it does nothing, the @ symbol stands for
"treat the string as a raw string and don't escape nothing"

So if you are (for example) using a string to store a path
you can do that in the two following ways:

string path = "c:\\windows\\system32"

or

string path = @"c:\windows\system32"

You gain the same behavior with other escape chars (\n, \t and so on)
2) Is there a performance loss if I start concatenating strings together
with the + operator ? In Java, they discouraged code like this:

string command = "CMD " + var1 + " " + var2;

The reason is because of all of the temporary String objects that get
created in the meantime. The solution is to use a StringBuffer like so:

StringBuffer command = new StringBuffer("CMD ");
command.append(var1);
command.append(' ');
command.append(var2);
System.out.println(command.toString());

Yeah, in .NET is pretty the same thing. It's discouraged to concatenate
strings cause they are "immutable" (a Python definition) and every
"string1" + "string2" generates a new instance (AFAIK). So .NET put in
place a class called StringBuilder (used in the same way as the
StringBufffer above) in the System.Text namespace

example:

using System.Text;

..... blah blah...

StringBuilder command = new StringBuilder("CMD ");
command.Append(var1);
command.Append(" ");
command.Append(var2);
Console.WriteLine(command.ToString());
 
StringBuilder is more efficient when firing off a lot of manipulation.

Inefficient
----------
string x = "something";
x += "Something else";
x += "Something else";
x += "Something else";
x += "Something else";
x += "Something else";

It would be better to use StringBuilder here.

string x = "something" + var1 + "something else" + var2;

Not a big issue here, as the end string is not being manipulated over and
over again (creating a new string each time). If you are simply concating,
adding to a string is fine. The benefit of the StringBuilder is cleaner
code, but more typing, especially when concating 100s of variables.


--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA

**********************************************************************
Think Outside the Box!
**********************************************************************
 
Hi,

Answers inline...

Regards,
Madhu

MVP | MCSD.NET
-----Original Message-----
I have a couple of questions regarding C# strings.

1) Sometimes I see a string in someone else's code like:

string foo = @"bar";

What does the '@' do for you?
All the escape sequence are not processed if you have
the '@' character. thus making things very simple.
for example: if you want the string to have the value
c:\docs\sample.txt, you can write it in two ways,
string foo = "c:\\docs\\sample.txt";
or
string foo = @"c:\docs\sample.txt";
2) Is there a performance loss if I start concatenating strings together
with the + operator ? In Java, they discouraged code like this:

string command = "CMD " + var1 + " " + var2;

The reason is because of all of the temporary String objects that get
created in the meantime. The solution is to use a StringBuffer like so:

StringBuffer command = new StringBuffer("CMD ");
command.append(var1);
command.append(' ');
command.append(var2);
System.out.println(command.toString());

This is less expensive than the above code because String objects are not
being created left & right. Does C# have the same problem? I noticed that
C# has a StringBuilder class which is just like the Java StringBuffer class.
Should I use StringBuffer in cases like the above where I need to
concatenate multiple strings to one string?
You are right!!! because in both the cases String is
immutable and thus creates lot of string objects.
 
Trevor said:
I have a couple of questions regarding C# strings.

1) Sometimes I see a string in someone else's code like:

string foo = @"bar";

What does the '@' do for you?

It makes it a "verbatim string literal" which means you don't have to
escape backslashes and the like.
2) Is there a performance loss if I start concatenating strings together
with the + operator ? In Java, they discouraged code like this:

string command = "CMD " + var1 + " " + var2;

The reason is because of all of the temporary String objects that get
created in the meantime. The solution is to use a StringBuffer like so:

StringBuffer command = new StringBuffer("CMD ");
command.append(var1);
command.append(' ');
command.append(var2);
System.out.println(command.toString());

This is less expensive than the above code because String objects are not
being created left & right.

It's really *not* any less expensive. Please read
http://www.pobox.com/~skeet/java/stringbuffer.html for more
information.

..NET's StringBuilder is indeed very similar to Java's StringBuffer, and
is useful in exactly the same circumstances - which doesn't include the
above.
 
Joe Mayo said:
Please see response in-line.

[Please fix your posting style so your response doesn't end up below
your sig separator, otherwise clients which automatically strip sigs
end up having problems quoting your post.]
Yes, there is a performance penalty with these concatenations because
of new string objects being created on each concatenation. The string
type is immutable.

No, there's no performance penalty above. Only a single string is being
created, as the above gets turned into

string command = String.Concat ("CMD ", var1, " ", var2);
 
Nicholas Paldino said:
Underneath the covers, Concat uses a StringBuilder instance to do its
work.

Are you sure? While I'd agree it'll do the same kind of thing, I can't
see why it would actually need to use StringBuilder itself.
 
I could have sworn that I saw a StringBuilder there somewhere. Anyways,
in the end, they all use internal methods on the String class to do its
work.
 
Jon Skeet said:
Joe Mayo said:
Please see response in-line.

[Please fix your posting style so your response doesn't end up below
your sig separator, otherwise clients which automatically strip sigs
end up having problems quoting your post.]

can do.
No, there's no performance penalty above. Only a single string is being
created, as the above gets turned into

string command = String.Concat ("CMD ", var1, " ", var2);


Hey Jon,

This is what I'm talking about. What do you mean that there is no perf
penalty in using the concatenation operator over StringBuilder?

using System;
using System.Collections;

namespace ConsoleTest
{
class MyTest
{
static void Main()
{
DateTime start = DateTime.Now;

string command = "";

for (int i=0; i < 80000; i++)
{
command += "string";
}

Console.WriteLine("With +: {0}", DateTime.Now - start);

start = DateTime.Now;

System.Text.StringBuilder cmdStr = new System.Text.StringBuilder();

// I jacked up the iterations just
// to get a clock on StringBuilder
for (int i=0; i < 80000; i++)
{
cmdStr.Append("string");
}

Console.WriteLine("With StringBuilder: {0}", DateTime.Now - start);

Console.ReadLine();
}
}
}

Joe
 
I could have sworn that I saw a StringBuilder there somewhere. Anyways,
in the end, they all use internal methods on the String class to do its
work.
Yeah, I don't think it does. With Reflector, here's the code (1.1fw)
public static string Concat(string str0, string str1, string str2)
{ int num1;
string text1;
if (((str0 == null) && (str1 == null)) && (str2 == null))
{
return string.Empty;
}
if (str0 == null)
{
str0 = string.Empty;

}
if (str1 == null)
{
str1 = string.Empty;

}
if (str2 == null)
{
str2 = string.Empty;

}
num1 = ((str0.Length + str1.Length) + str2.Length);
text1 = string.FastAllocateString(num1); //internal call, allocates
memory for the string
string.FillStringChecked(text1, 0, str0); //internal call, writes the
source string to the newly allocated memory
string.FillStringChecked(text1, str0.Length, str1);
string.FillStringChecked(text1, (str0.Length + str1.Length), str2);
return text1;
}

Austin
 
Austin said:
Yeah, I don't think it does. With Reflector, here's the code (1.1fw)
public static string Concat(string str0, string str1, string str2)
{ int num1;
string text1;
if (((str0 == null) && (str1 == null)) && (str2 == null))
{
return string.Empty;
}
if (str0 == null)
{
str0 = string.Empty;

}
if (str1 == null)
{
str1 = string.Empty;

}
if (str2 == null)
{
str2 = string.Empty;

}
num1 = ((str0.Length + str1.Length) + str2.Length);
text1 = string.FastAllocateString(num1); //internal call, allocates
memory for the string
string.FillStringChecked(text1, 0, str0); //internal call, writes the
source string to the newly allocated memory
string.FillStringChecked(text1, str0.Length, str1);
string.FillStringChecked(text1, (str0.Length + str1.Length), str2);
return text1;
}

Austin

The key point is that it allocates only one string, then copies the
contents of the parameter strings into the destination string's buffer.

This is very close to a StringBuilder style, however it's a bit lighter
weight since it doesn't have even the overhead of constructing the
StringBUilder object - it goes right to the string.

That said, all of the previous postings that indicated using a
StringBuilder would be more efficient in this case (a single assignment
with multiple concatenations) are probably wrong, if only slightly
(maybe not even measurably).
 
That said, all of the previous postings that indicated using a
StringBuilder would be more efficient in this case (a single assignment
with multiple concatenations) are probably wrong, if only slightly
(maybe not even measurably).

Basically, if it's in a loop, StringBuilder. If it's +=,
StringBuilder. If it's str=var1+var2+var3, string should be fine.

Loops are about the only place there would be any noticeably
difference in perf/memory consumation.

Austin
 
Just remember that strings are immutable for a reason: thread safety,
and you lose that if you go with StringBuilder. But then again,
StringBuilder was created for a reason too.
 
Joe Mayo said:
This is what I'm talking about. What do you mean that there is no perf
penalty in using the concatenation operator over StringBuilder?

<snip>

I mean exactly that - for the example given by the original poster.
Your benchmark tested *repeated* concatenations to build up a single
long string. The original poster gave an example of a single statement
of concatenation, which isn't the same thing at all.

Try your benchmark again but with:

// Declare these somewhere
string var1 = "hello";
string var2 = "there";

// Test concatenation
for (int i=0; i < 80000; i++)
{
string command = "PREFIX "+var1+" "+var2;
}

// ...

// Test StringBuilder
for (int i=0; i < 80000; i++)
{
StringBuilder sb = new StringBuilder();
sb.Append ("PREFIX ");
sb.Append (var1);
sb.Append (" ");
sb.Append (var2);
string command = sb.ToString();
}

I'd expect the concatenation to be faster if anything, as it doesn't
create as many objects.

See http://www.pobox.com/~skeet/java/stringbuffer.html for more
explanation. It's Java-based, but the principles are much the same
(except C# doesn't use StringBuilder internally to concatenate).
 
Steve said:
Just remember that strings are immutable for a reason: thread safety,
and you lose that if you go with StringBuilder. But then again,
StringBuilder was created for a reason too.

Strings are immutable for much more than thread safety. They're for
parameter safety in general - you wouldn't be able to pass or return
strings anywhere without taking a copy if they weren't immutable,
unless you didn't care whether or not they changed.
 
Jon Skeet said:
Try your benchmark again but with:

// Declare these somewhere
string var1 = "hello";
string var2 = "there";

// Test concatenation
for (int i=0; i < 80000; i++)
{
string command = "PREFIX "+var1+" "+var2;
}

// ...

// Test StringBuilder
for (int i=0; i < 80000; i++)
{
StringBuilder sb = new StringBuilder();
sb.Append ("PREFIX ");
sb.Append (var1);
sb.Append (" ");
sb.Append (var2);
string command = sb.ToString();
}

I'd expect the concatenation to be faster if anything, as it doesn't
create as many objects.

Thanks Jon, I'm glad you pointed that out. I played around with the code,
looked at the IL to see what the C# compiler was doing, and see what you are
talking about now.

Joe
 
Back
Top