This question already has answers here:
String output: format or concat in C#?
(32 answers)
Closed 8 years ago.
Here is 2 methods which result the same:
public class MessageManager
{
public void SendMessage(string name, int count)
{
string message = "Hi " + name + ". I know you don't like cake, so I bought you " + count + " lollipops. Same thing, right?"; // No boxing. "count" was converted to string somehow.
//Console.WriteLine(message);
}
public void SendMessage2(string name, int count)
{
string message = String.Format("Hi {0}. I know you don't like cake, so I bought you {1} lollipops. Same thing, right?", name, count); // Boxing "name" and "count" + executing unnecessary code.
//Console.WriteLine(message);
}
}
So I guess the second method will be slower then first because of boxing and executing some additional code which inside String.Format() method.
I have tested them with following method:
public static class PerformanceTester
{
public static TimeSpan TestAction(Action<string, int> action)
{
Stopwatch timer = new Stopwatch();
timer.Start();
for (ushort i = 0; i < ushort.MaxValue; i++)
action("Alex", 1000);
timer.Stop();
return timer.Elapsed;
}
}
And here is the usage of it:
static void Main(string[] args)
{
MessageManager mm = new MessageManager();
TimeSpan ts_m1 = PerformanceTester.TestAction(new Action<string, int>(mm.SendMessage));
TimeSpan ts_m2 = PerformanceTester.TestAction(new Action<string, int>(mm.SendMessage2));
Console.WriteLine("First message took time: " + ts_m1.ToString());
Console.WriteLine("Second message took time: " + ts_m2.ToString());
Console.ReadKey();
}
Output with my Intel® Core™2 Duo Processor E8200 (DEBUG):
Output with my Intel® Core™2 Duo Processor E8200 (RELEASE):
I saw String.Format used almost everywhere (guides, blogs, tutorials etc.) but it is actually slower than simple string concatenation. I know when I talk about C# I must not care about performance, but the results in this example is too awesome.
The question is: "Is there any best practice where String.Format is actually better than concatenation of strings."
It's largely a matter of style. However, consider more complex formatting. For example you want to format a bunch of stuff:
var s = String.Format("{0,10:N2} {1,-20} {2:P2}", val, description, (val/100));
Or ...
var s = val.ToString("10:N2") + string.Format("{0,-20}", desc) + (val/100).ToString("P2");
I like the String.Format call there much better. It separates the formatting from the content in much the way that CSS separates the presentation from the HTML content. When I'm writing or examining code that formats output, I typically want to see the format at a glance. The actual values being formatted aren't relevant when I'm debugging a formatting issue.
With concatenation, I have to slog my way through the individual values to see what the format is for each item.
Finally, does performance really matter here? Most programs spend precious little time formatting their output. Optimizing the formatting code seems like a huge waste of time. Write whatever is easier to maintain and prove correct.
string.format is as the name suggest for formatting strings. you can take the format string and stick it in a resource or have it translated. it is not about performance and it is not about readability. simple string concatenation is ok if you do let's say less than 5. if you want to concatenate more strings and want to consider the performance - use StringBuilder.
Related
Hey guys so I made this function which is called every frame.
- You think this is a good way to save performance or is there a better way?
private void GetCurrentTime()
{
m_TimeNow = System.Convert.ToString(System.DateTime.Now);
//If the previous time is not equals to the current time (without seconds = every minute)
if (m_PreTime != m_TimeNow.Remove(14))
{ //Change the Time displayed on the screen:
m_PreTime = m_TimeNow.Remove(14); //1. Copy current Time
m_Times = m_TimeNow.Split(' '); //2. Split to following parts
m_Time = m_Times[1].Remove(4); //3. Cutout seconds
m_Text_Time.text = m_Time + " " + m_Times[2]; //4. And change UI-Text: Time + AM/PM
}
}
This function is called every Frame and will be on a mobile android device.
Thanks!
I may see some improvements in your implementation. Here is what I can tell you from my own experience.
For a short answer, this his how I would write your function:
//
// Version 2
//
class TimerExample_V2 {
private DateTime _TimeNow = System.DateTime.Now;
private DateTime _PreTime = System.DateTime.Now;
private string _format = "t";
private string _cultureName = "en-US";
public TimerExample_V2() {
CultureInfo culture = new CultureInfo(_cultureName);
CultureInfo.CurrentCulture = culture;
}
public void UpdateCurrentTimeUI() {
_TimeNow = System.DateTime.Now;
if(_PreTime.Minute != _TimeNow.Minute) {
// Note: this case appear only once per minute.
_PreTime = System.DateTime.Now;
string newText = _TimeNow.ToString(_format);
//m_Text_Time.text = newText; // Update unity display
// I omit this display unity. (Same cost in both case)
}
}
Now for a longer answer with explanations:
Strings (Performance):
Strings are generally costly, specially when dealing with str processing and comparisons. For instance 'String.Remove(int)' creates a new string, which may call several costly methods such as malloc etc (Behind the scene). As far as I see, you keep all your dates as strings but could use only the raw format DateTime. A better approach would be to keep your data in the 'DateTime' format and convert them as a string only for the end user. (For instance, to update your Unity display). It is better to compare two int (ex: DateTime.ElapsedMilliseconds) than string (ex: m_PreTime != m_TimeNow.Remove(14))
Date format (Flexibility):
You would have several issues when dealing with different date formats. Your implementation expects "HH:mm AM / PM" format, but user may have a possibility to change the format (24h for instance).. Use the dark magic power that C# gives you. For instance, use the CultureInfo or the already implemented "DateTime.ToString(format)". (I just learned about 'CultureInfo'. There may be other ways. But as a general rule, see whether the language already has the feature you need).
Functions name:
This is a little thing, but try to have little functions that does what it says. In your case, from 'GetCurrentTime', we would expect a return value. This function actually update a display and return void. Something like 'UpdateTimeDisplay' is probably better.
Duplicate calls:
A second little thing: you have 2 calls to m_timeNow.Remove(14). You could create a new string once (From this function) and use this new string in both places.
Experiment (Measurements and validation)
Anyway, when dealing with performance, you have to measure, benchmark your code. (As an example, I first did an implementation for your GetCurrentTime and realized it wasn't actually better.). The following is a little experiemnt I created to show you some measurement. I'm not a C# shaman expert, nor a performance wizard expert but I hope my example is clear enought. I run the experiment on my laptop: (Intel i5-3320M CPU # 2.60GHz).
I have two implementations of your function. I run 10 000 times each function and print the execution time for each. (I omit the call to update the unity display, which is the same in both cases). My measurements show that your implementation took 45 ms, the other took 23 ms.
The second implementation sounds better. However, don't forget that I called 10 000 times the functions. In practice, with 60fps, you call the update 60 times per seconds. On my laptop, 60 iterations took 0 miliseconds for both.
There is another element to point out:
m_PreTime = m_TimeNow.Remove(14);
m_Times = m_TimeNow.Split(' ');
m_Time = m_Times[1].Remove(4);
These are kind of slow functions since dealing with strings creation. However, there are called only once per minute. As a matter of fack, I measured that, my implementation, when switching minute, uses the same amount of milliseconds as your. I may have failed my measurement or whatever, but maybe, once each minute, my function takes as much time as your. In all other cases, it is 'faster'. I may summerize this point using a quote:
"Solve for the most common case first, Not for the most generic"
(As far as I remember, this is a quote from the talk about optimization: https://www.youtube.com/watch?v=nXaxk27zwlk. Good talk btw)
Experiment (Source code)
So here is the full code of my terrible experiment:
using System;
using System.Globalization;
using System.Diagnostics;
// Instructions to compile (With mono)
// csc Program.cs
// mono Program.exe
class Program {
static void Main(string[] args) {
TimerExample_V1 timer_v1 = new TimerExample_V1();
TimerExample_V2 timer_v2 = new TimerExample_V2();
Stopwatch profiler;
int nbBenchLoops = 10000; // 10 000 times
float t1;
float t2;
// Profil version 1
profiler = Stopwatch.StartNew();
for(int k = 0; k < nbBenchLoops; ++k) {
timer_v1.UpdateCurrentTimeUI();
}
t1 = profiler.ElapsedMilliseconds;
// Profil version 2
profiler = Stopwatch.StartNew();
for(int k = 0; k < nbBenchLoops; ++k) {
timer_v2.UpdateCurrentTimeUI();
}
t2 = profiler.ElapsedMilliseconds;
// Print mesured times
Console.WriteLine("[SCOPE_PROFILER] [Version 1]: {0} ms", t1);
Console.WriteLine("[SCOPE_PROFILER] [Version 2]: {0} ms", t2);
}
}
//
// Version 1
//
class TimerExample_V1 {
private string m_TimeNow = System.Convert.ToString(System.DateTime.Now);
private string m_PreTime = System.Convert.ToString(System.DateTime.Now);
private string[] m_Times;
private string m_Time;
public void UpdateCurrentTimeUI() {
m_TimeNow = System.Convert.ToString(System.DateTime.Now);
if (m_PreTime != m_TimeNow.Remove(14)) {
// Note: this case appear only once per minute.
m_PreTime = m_TimeNow.Remove(14);
m_Times = m_TimeNow.Split(' ');
m_Time = m_Times[1].Remove(4);
string newText = m_Time + " " + m_Times[2];
//m_Text_Time.text = newText; // Update unity display
// I omit this display unity. (Same cost in both case)
}
}
}
//
// Version 2
//
class TimerExample_V2 {
private DateTime _TimeNow = System.DateTime.Now;
private DateTime _PreTime = System.DateTime.Now;
private string _format = "t";
private string _cultureName = "en-US";
public TimerExample_V2() {
CultureInfo culture = new CultureInfo(_cultureName);
CultureInfo.CurrentCulture = culture;
}
public void UpdateCurrentTimeUI() {
_TimeNow = System.DateTime.Now;
if(_PreTime.Minute != _TimeNow.Minute) {
// Note: this case appear only once per minute.
_PreTime = System.DateTime.Now;
string newText = _TimeNow.ToString(_format);
//m_Text_Time.text = newText; // Update unity display
// I omit this display unity. (Same cost in both case)
}
}
}
For further information about DateTime.ToString and CultureInfo, checkout the documentation:
CultureInfo C# Documentation
DateTime.ToString C# Documentation
Hope this will help :)
Consider the following situation:
public class Employee
{
public string Name {get; set}
public string Email {get; set}
}
public class EnployeeGroup
{
//List of employees in marketting
public IList<Employee> MarkettingEmployees{ get; }
//List of employees in sales
public IList<Employee> SalesEmployees{ get; }
}
private EnployeeGroup GroupA;
int MarkettingCount;
string MarkettingNames;
MarkettingCount = GroupA.MarkettingEmployees.Count; //assigns MarkettingCount=5, this will always be 5-10 employees
MarkettingNames = <**how can i join all the GroupA.MarkettingEmployees.Name into a comma separated string?** >
//I tried a loop:
foreach(Employee MktEmployee in GroupA.MarkettingEmployees)
{
MarkettingNames += MktEmployee.Name + ", ";
}
The loop works, but i want to know:
Is Looping the most efficient/elegant way of doing this? If not then what are the better alternatives? I tried string.join but couldnt get it working..
I want to avoid Linq..
You need a little bit of LINQ whether you like it or not ;)
MarkettingNames = string.Join(", ", GroupA.MarkettingEmployees.Select(e => e.Name));
From a practicality standpoint, there's no reasonable argument for avoiding a loop. Iterations are at the hard of every general-purpose programming language.
Using LINQ is elegant in simple cases. Again, there's no sound reason to avoid it per se.
In case you are looking for a rather obscure, academic solution, there's always tail recursion. However, your data structure would have to be adapted for it. Note that even if you use it, a smart compiler will detect it and optimize into a loop. The odds are agains you!
As an alternative you could use a StringBuilder with Append instead of creating a new string at each iteration
This would be much more efficient (see caveat below):
var stringBuilder = new StringBuilder();
foreach (Employee MktEmployee in GroupA.MarkettingEmployees)
{
stringBuilder.Append(MktEmployee.Name + ", ");
}
Then this:
foreach(Employee MktEmployee in GroupA.MarkettingEmployees)
{
MarkettingNames += MktEmployee.Name + ", ";
}
Edit: If you were to have a large amount of employees this would be much more efficient. However, a trivial loop of 5-10 is actually slightly less efficient.
In small cases - this isn't going to be that large of a hit on performance, but in large cases the pay off will be significant.
Also, if you are to use the explicit loop approach, it's probably best to trim off that last ", " by using something like:
myString = myString.Trim().TrimEnd(',');
The article below explains when you should use StringBuilder to concatenate strings.
In short, in the approach you use: the concatenation is creating a new string each time, which obviously eats up a lot of memory. You also need to copy all the data from the existing string of MarkettingNames to the new string being appended yet another MktEmployee.Name + ", ".
Thank you, Jon Skeet: http://www.yoda.arachsys.com/csharp/stringbuilder.html
I want to know how return values for strings works for strings in C#. In one of my functions, I generate html code and the string is really huge, I then return it from the function, and then insert it into the page. But I want to know should I pass a huge string as a return value, or just insert it into the page from the same function?
When C# returns a string, does it create a new string from the old one, and return that?
Thanks.
Strings (or any other reference type) are not copied when returning from a function, only value types are.
System.String is a reference type (class) and so passing as parameter and returning only involve the copying of a reference (32 or 64 bits).
The size of the string is not relevant.
Returning a string is a cheap operation - as mentioned it's purely a matter of returning 32 or 64 bits (4 or 8 bytes).
However, as Sten Petrov points out string + operations involve the creation of a new string, and can be a little expensive. If you wanted to save performance & memory I'd suggest doing something like this:
static int i = 0;
static void Main(string[] args)
{
while (Console.ReadLine() == "")
{
var pageSB = new StringBuilder();
foreach (var section in new[] { AddHeader(), AddContent(), AddFooter() })
for (int i = 0; i < section.Length; i++)
pageSB.Append(section[i]);
Console.Write(pageSB.ToString());
}
}
static StringBuilder AddHeader()
{
return new StringBuilder().Append("Hi ").AppendLine("World");
}
static StringBuilder AddContent()
{
return new StringBuilder()
.AppendFormat("This page has been viewed: {0} times\n", ++i);
}
static StringBuilder AddFooter()
{
return new StringBuilder().Append("Bye ").AppendLine("World");
}
Here we use the StringBuilders to hold a reference to all the strings we want to concat, and wait until the very end before joining them together. This'll save many unnecessary additions (which are memory and CPU heavy in comparison).
Of course, I doubt you'll actually see any need for this in practise - and if you do I'd spend some time learning about pooling etc. to help reduce the garbage created by all the string builders - and maybe consider creating a custom 'string holder' that suits your purposes better.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I have always hated string parsing, something I am doing a lot of in a current project.
Does c# have and tricks or quick features for strings that would make my life easier? In particular cropping, multiplying or substringing? The end goal here is to take a list of string and turn it into a nice pretty columned structure. Easy, but still, I would it to be python easy.
For example, python has:
>>> a = "I once was a string, then I got mutilated"
>>> print a[20:]
then I got mutilated
or
>>> 'chicken' in 'chicken noodle soup'
True
or finally
>>> 'lol' * 5
'lollollollollol'
There aren't language related features for this in C# like there are in Python. The only real C# language feature with strings is allowing + to be mapped to String.Concat, to simplify (and keep efficient) "a" + "b" + "c" statements.
The String class provides this functionality via methods, however. There is also StringBuilder, which is used for building large strings based on multiple concatenations.
In your example, see String.Substring for slicing and String.Contains for in. There isn't a simple "repeat" style operation like the multiplication in Python.
That being said, it's easy to make an extension method which handles the multiply functionality.
They're different languages - the syntax is different and comparing C# to Python in this way is largely pointless. Also I completely challenge your assertion that the examples you've given are 'easier'.
I don't see how you can get much easier than:
Console.WriteLine("Foo".Substring(1)); //<-- prints 'oo'
Console.WriteLine("chicken noodle soup".Contains("chicken")
.ToString()); //<-- prints 'true'
And for the last one, read this SO: Can I "multiply" a string (in C#)?
Personally, in particular, I hate the idea of multiplying a string - too much ambiguity if that value happens to be '5' - hiding such functionality behind operators smells.
First Question
You can use String.SubString():
string a = "I once was a string, then I got mutilated";
string lastTwentyCharactersOfA = a.Substring(Math.Max(0, a.Length - 20));
// returns "then I got mutilated"
Credit where credit is due: This answer does a nice job of making sure that you don't get an exception if your string has less characters than you are requesting.
Second Question
You can use String.Contains():
string soup = "chicken noodle soup";
bool soupContainsChicken = soup.Contains("chicken"); // returns True
Third Question
You can't override the multiplication operator for the String class. It's a sealed class, and of course you don't have access to the source code to make it a partial class or something along those lines. You have a couple of options that will get you close to what you want to do. One is to write an extension method:
public static string MultiplyBy(this string s, int times)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < times; i++)
{
sb.Append(s);
}
return sb.ToString();
}
Usage:
string lol = "lol";
string trololol = lol.MultiplyBy(5); // returns "lollollollollol"
Or if you want to go the route of operator overloading, you can write a custom String class of sorts and then have at it.
public struct BetterString // probably not better than System.String at all
{
public string Value { get; set; }
public static BetterString operator *(BetterString s, int times)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < times; i++)
{
sb.Append(s.Value);
}
return new BetterString { Value = sb.ToString() };
}
}
Usage:
BetterString lol = new BetterString { Value = "lol" };
BetterString trololol = lol * 5; // trololol.Value is "lollollollollol"
In general, there's a lot you can do with System.String and System.Text.StringBuilder. And the possibilities are almost endless with extension methods. Check out MSDN if you are interested in learning the ins and outs of it all.
using linq, you can treat your string like a list of chars and do what you want easy enough.
var chickenString = "chicken noodle soup";
var hasChicken = chickenString.Contains("chicken");
// hasChicken = true at this point...
I have a string in which I need to replace markers with values from a dictionary. It has to be as efficient as possible. Doing a loop with a string.replace is just going to consume memory (strings are immutable, remember). Would StringBuilder.Replace() be any better since this is was designed to work with string manipulations?
I was hoping to avoid the expense of RegEx, but if that is going to be a more efficient then so be it.
Note: I don't care about code complexity, only how fast it runs and the memory it consumes.
Average stats: 255-1024 characters in length, 15-30 keys in the dictionary.
Using RedGate Profiler using the following code
class Program
{
static string data = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
static Dictionary<string, string> values;
static void Main(string[] args)
{
Console.WriteLine("Data length: " + data.Length);
values = new Dictionary<string, string>()
{
{ "ab", "aa" },
{ "jk", "jj" },
{ "lm", "ll" },
{ "yz", "zz" },
{ "ef", "ff" },
{ "st", "uu" },
{ "op", "pp" },
{ "x", "y" }
};
StringReplace(data);
StringBuilderReplace1(data);
StringBuilderReplace2(new StringBuilder(data, data.Length * 2));
Console.ReadKey();
}
private static void StringReplace(string data)
{
foreach(string k in values.Keys)
{
data = data.Replace(k, values[k]);
}
}
private static void StringBuilderReplace1(string data)
{
StringBuilder sb = new StringBuilder(data, data.Length * 2);
foreach (string k in values.Keys)
{
sb.Replace(k, values[k]);
}
}
private static void StringBuilderReplace2(StringBuilder data)
{
foreach (string k in values.Keys)
{
data.Replace(k, values[k]);
}
}
}
String.Replace = 5.843ms
StringBuilder.Replace #1 = 4.059ms
Stringbuilder.Replace #2 = 0.461ms
String length = 1456
stringbuilder #1 creates the stringbuilder in the method while #2 does not so the performance difference will end up being the same most likely since you're just moving that work out of the method. If you start with a stringbuilder instead of a string then #2 might be the way to go instead.
As far as memory, using RedGateMemory profiler, there is nothing to worry about until you get into MANY replace operations in which stringbuilder is going to win overall.
This may be of help:
https://learn.microsoft.com/en-us/archive/blogs/debuggingtoolbox/comparing-regex-replace-string-replace-and-stringbuilder-replace-which-has-better-performance
The short answer appears to be that String.Replace is faster, although it may have a larger impact on your memory footprint / garbage collection overhead.
Would stringbuilder.replace be any better [than String.Replace]
Yes, a lot better. And if you can estimate an upper bound for the new string (it looks like you can) then it will probably be fast enough.
When you create it like:
var sb = new StringBuilder(inputString, pessimisticEstimate);
then the StringBuilder will not have to re-allocate its buffer.
Yes, StringBuilder will give you both gain in speed and memory (basically because it won't create an instance of a string each time you will make a manipulation with it - StringBuilder always operates with the same object). Here is an MSDN link with some details.
Converting data from a String to a StringBuilder and back will take some time. If one is only performing a single replace operation, this time may not be recouped by the efficiency improvements inherent in StringBuilder. On the other hand, if one converts a string to a StringBuilder, then performs many Replace operations on it, and converts it back at the end, the StringBuilder approach is apt to be faster.
Rather than running 15-30 replace operations on the entire string, it might be more efficient to use something like a trie data structure to hold your dictionary. Then you can loop through your input string once to do all your searching/replacing.
It will depend a lot on how many of the markers are present in a given string on average.
Performance of searching for a key is likely to be similar between StringBuilder and String, but StringBuilder will win if you have to replace many markers in a single string.
If you only expect one or two markers per string on average, and your dictionary is small, I would just go for the String.Replace.
If there are many markers, you might want to define a custom syntax to identify markers - e.g. enclosing in braces with a suitable escaping rule for a literal brace. You can then implement a parsing algorithm that iterates through the characters of the string once, recognizing and replacing each marker that it finds. Or use a regex.
My two cents here, I just wrote couple of lines of code to test how each method performs and, as expected, result is "it depends".
For longer strings Regex seems to be performing better, for shorter strings, String.Replace it is. I can see that usage of StringBuilder.Replace is not very useful, and if wrongly used, it could be lethal in GC perspective (I tried to share one instance of StringBuilder).
Check my StringReplaceTests GitHub repo.
The problem with #DustinDavis' answer is that it recursively operates on the same string. Unless you're planning on doing a back-and-forth type of manipulation, you really should have separate objects for each manipulation case in this kind of test.
I decided to create my own test because I found some conflicting answers all over the Web, and I wanted to be completely sure. The program I am working on deals with a lot of text (files with tens of thousands of lines in some cases).
So here's a quick method you can copy and paste and see for yourself which is faster. You may have to create your own text file to test, but you can easily copy and paste text from anywhere and make a large enough file for yourself:
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Windows;
void StringReplace_vs_StringBuilderReplace( string file, string word1, string word2 )
{
using( FileStream fileStream = new FileStream( file, FileMode.Open, FileAccess.Read ) )
using( StreamReader streamReader = new StreamReader( fileStream, Encoding.UTF8 ) )
{
string text = streamReader.ReadToEnd(),
#string = text;
StringBuilder #StringBuilder = new StringBuilder( text );
int iterations = 10000;
Stopwatch watch1 = new Stopwatch.StartNew();
for( int i = 0; i < iterations; i++ )
if( i % 2 == 0 ) #string = #string.Replace( word1, word2 );
else #string = #string.Replace( word2, word1 );
watch1.Stop();
double stringMilliseconds = watch1.ElapsedMilliseconds;
Stopwatch watch2 = new Stopwatch.StartNew();
for( int i = 0; i < iterations; i++ )
if( i % 2 == 0 ) #StringBuilder = #StringBuilder .Replace( word1, word2 );
else #StringBuilder = #StringBuilder .Replace( word2, word1 );
watch2.Stop();
double StringBuilderMilliseconds = watch1.ElapsedMilliseconds;
MessageBox.Show( string.Format( "string.Replace: {0}\nStringBuilder.Replace: {1}",
stringMilliseconds, StringBuilderMilliseconds ) );
}
}
I got that string.Replace() was faster by about 20% every time swapping out 8-10 letter words. Try it for yourself if you want your own empirical evidence.