1

A colleague told me that using the following method:

 string url = "SomeURL";
 string ext = "SomeExt";
 string sub = "SomeSub";
 string subSub = "moreSub";
 string Url = @"http://www." + Url +@"/"+ ext +@"/"+  sub  + subSub;

is not efficenet (takes more resources) and it is preferred to use the following method:

 string Url = @"http://www.#URL.#EXT/#sub/#subSub";
 string url = "SomeURL";
 string ext = "SomeExt";
 string sub = "SomeSub";
 string subSub = "moreSub";
 Url = Url.Replace("#URL",url)
 Url = Url.Replace("#EXT",ext);
 Url = Url.Replace("#sub",sub);
 Url = Url.Replace("#subSub",subSub);

Is that true? and what is the explanation behind it?

I read this Answer and it got me wondering what about this case :

 string Url = @"http://www.#URL.#EXT/#sub/#subSub";
 string url = "SomeURL";
 string ext = "SomeExt";
 string sub = "SomeSub";
 string subSub = "moreSub";
string finalUrl = new StringBuilder(Url )
        .Replace("#URL", "URL")
        .Replace("#EXT", "EXT")
        .Replace("#sub", "sub")
        .Replace("#subSub", "subSub")
        .ToString();

is that more efficenet then ??

Community
  • 1
  • 1
Madi D.
  • 1,980
  • 5
  • 23
  • 44

7 Answers7

8

Your colleague is completely wrong.

He is mis-applying the fact that strings are immutable, and that appending two strings will create a third string object.
Your method (a + b + c) is the most efficient way to do this.
The compiler transforms your code into a call to String.Concat(string[]), which uses unsafe code to allocate a single buffer for all of the strings and copy them into the buffer.

His advice should be to use a StringBuilder when concatenating strings in a loop.

EDIT: String.Concat (which is equivalent to + concatenation, like your first example) is the fastest way to do this. Using a StringBuilder like in your edit will be slower, because it will need to resize the string during each Replace call.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • -1 because its not the most effecient way to do this .. using stringbuilder is more effecient – Hiyasat Dec 20 '10 at 15:31
  • @peacmaker **WRONG!** If you don't have a loop, a `StringBuilder` is _slower_. Calling Concat (`+`) will allocate a single string of the correct size; a `StringBuilder` will need to re-allocate. Please do not downvote without knowing what you're talking about. – SLaks Dec 20 '10 at 15:34
8

It is not true, you can't see it because the code is wrong. It should be:

Url = Url.Replace("#URL", url);
Url = Url.Replace("... etc");

You can usually make string concatenation more efficient by using StringBuilder. However, that can only do a better job with so few strings if you can accurately guess the Capacity you need. Your specific code however gets optimized by the compiler to an overload of String.Concat() that takes multiple strings. Which uses an internal high-speed concatenator, impossible to beat with StringBuilder.

Take advantage from the composite formatting feature available in String.Format:

string Url = string.Format(@"http://www.{0}/{1}/{2}{3}", url, ext, sub, subSub);

Quick and readable.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 7
    Using StringBuilder *wouldn't* make the concatenation more efficient. It's a single expression - the compiler will make a single call to String.Concat. – Jon Skeet Apr 25 '10 at 14:48
5

Firstly, I'm almost certain that replace is not more efficient than concatenation. If anything, it is probably even less efficient.

Secondly, your code with replace actually will not work as you expect. The Replace method does not change string. (string cannot be changed, by the way; ever) Instead, the Replace method returns a new string. And the old one stays the same. Therefore, in order for it to work, you should write:

Url = Url.Replace("#URL",url)
Url = Url.Replace("#EXT",ext);
Url = Url.Replace("#sub",sub);
Url = Url.Replace("#subSub",subSub);

Preferred method for things like this is using string.Format:

Url = string.Format( "http://www.{0}.{1}/{2}/{3}", url, ext, sub, subSub );

However, on small cases like yours (less than 10 concatenations, I would say), it is actually most efficient to use concatenation.

And lastly, if you have many concatenations (dozens), you should use StringBuilder.

Fyodor Soikin
  • 78,590
  • 9
  • 125
  • 172
  • Alternatively `Url = Url.Replace("#URL",url).Replace("#EXT",ext).Replace("#sub",sub).Replace("#subSub",subSub);` but agreed that `string.Format` should be the preferred method. – Davy8 Apr 25 '10 at 14:44
4

Your colleague is incorrect. The Replace() method (or any method which 'modifies' strings) creates a new string each time it is called. So calling it four times creates three more strings than you need to generate the output. Your first method creates only the one output string (not counting the strings which make up the components of the url).

Ray
  • 21,485
  • 5
  • 48
  • 64
  • @Fyodor: You are wrong. `str1 + str2 + str3` is transformed by the compiler into a single call to `String.Concat` – SLaks Apr 25 '10 at 14:42
  • There are seven strings being concatenated in this example. This will result in three `string.Concat` calls. – Fyodor Soikin Apr 25 '10 at 14:44
  • 1
    @Fyodor: You're still wrong. This will compile to a single call to `String.Concat` with seven arguments. – SLaks Apr 25 '10 at 14:46
  • 1
    There is no version of `Concat` with seven arguments. Only up to 4. And if you mean the one with `params String[]`, then it would involve creating an array. – Fyodor Soikin Apr 25 '10 at 14:49
  • 1
    @SLaks: No, it will actually create an array and call `String.Concat(string[])` (try it) - but it's still just a single call. – Jon Skeet Apr 25 '10 at 14:50
  • I just compiled some similar string concat code and checked the IL. Sure enough, it works as Jon says - string.Concat is called once with an array of strings. – Ray Apr 25 '10 at 14:57
  • So in both cases new strings will be created, but when i use str1+str2+str3 there will be less strings created? and less function calls ? – Madi D. Apr 25 '10 at 15:04
  • Correct. So it looks more efficient to do str1+str2+str3 rather than the multiple replace. But to be sure, you would have to do some performance tests comparing these two methods, plus the StringBuilder and Format() methods others have suggested. Unless this is some truly performance-critical code, I would suggest using str1+str2+str3 and moving on. – Ray Apr 25 '10 at 15:09
4

For only five strings, it doesn't really matter performance-wise. Use simple concatenation, string.Format(), Url.Replace(), whatever best displays the intent of what you are doing. This is far more important than micro-optimisations that are unlikely to work.

Remember that if you are concatenating many strings, it would be a good idea to use the StringBuilder class because otherwise large numbers of strings would be created and performance would be affected.

I would personally use string.Format in your case (more concise, all on one line, shows intent):

string Url = string.Format("http://www.{0}/{1}/{2}{3}", url, ext, sub, subSub);
Callum Rogers
  • 15,630
  • 17
  • 67
  • 90
1

Others have pointed out that your colleague is blowing smoke. I'd like to explain why he appears to be confused (but not exactly 100% wrong):

This code is efficient:

string url = "SomeURL";
string ext = "SomeExt";
string sub = "SomeSub";
string subSub = "moreSub";
string Url = @"http://www." + Url +@"/"+ ext +@"/"+  sub  + subSub;

It's efficient because there is only one concatenation happening (of multiple strings).

On the other hand, if you wrote it the following way, it would be very inefficient:

// BAD CODE!  Don't write this.
string url = "http://www.";
url += "SomeURL";
url += "/";
url += "SomeExt";
url += "/";
url += "SomeSub";
url += "moreSub";

The above code has to allocate a new string for every concatenation. If you do this on a few lines of code, it's not horrible, just bad. If you do it inside a tight loop, it's a performance killer.

If you compare the second version of the code to a version using string.Format:

string url = string.Format("http://www.{0}/{1}/{2}{3}",
    "SomeURL", "SomeExt", "SomeSub", "moreSub");

Then in this case, the string.Format (not string.Replace) version will be much faster, because it only has to construct one string.

So the answer as to whether or not string.Format is more efficient than concatenation depends on how you do the concatenation and how you do the format. A single concatenation (which can concatenate multiple strings, as I explained earlier) is far faster than a Format. But a series of sequential concatenations will be slower than a single Format.

In other words, concatenation is slower than Format (not Replace) if you mess the former up horribly.

Aaronaught
  • 120,909
  • 25
  • 266
  • 342
  • 1
    I suspect that the compiler would optimize your second example to be equivalent to the first. (At least in Release mode) – SLaks Apr 25 '10 at 15:05
  • 1
    @SLaks: That *may* be true if you use that code verbatim, but definitely won't be true in a loop, and is very unlikely to be true if any other statements happen between the concatenations. And even if the optimizer does manage to work this out, it's still a horrible practice to rely on such optimizations. – Aaronaught Apr 25 '10 at 15:08
-2

because when you use "+" you are creating a new object so its not efficenet

Hiyasat
  • 8,601
  • 7
  • 33
  • 59
  • 3
    You are wrong. `str1 + str2 + str3` is transformed by the compiler into a single call to `String.Concat` – SLaks Apr 25 '10 at 14:41