A couple of weeks ago, we discussed Value types and Reference types where we said that a reference type points to the value it represents and a value type is the value it represents.
This has implications when we work with the assignment operator because when you assign a reference type and change the content of what it is pointing to, both variables get changed because they are both pointing to the same location in memory. If you do this with a value type, only the one you change sees the change because you are working with a copy.
Is String A Value or Reference Type?
So, if you’ve done any work with the String class, you might think it is a value type, because if you write this code:
string a = "abc"; string b = a; string b = "def"; Console.WriteLine(a); Console.WriteLine(b);
You will quickly discover that the values that get written out are:
Which is not what you’d expect if String is a reference type.
So, the question we need to ask is, why is String acting like a value type if it is really a reference type?
Strings Are Immutable
The answer is that Strings are immutable. That is, a string never changes. And if you are a thinking person I can already hear you saying, “Sure they change, just look at this code…”
string a = "abc"; a = "def"; Console.WriteLine(a);
”See, I changed the string variable a from ‘abc’ to ‘def’”
And yes, you did change the a variable. But what did you change? You didn’t change “abc” to “def” you change what a was pointing to. You see, “abc” is the object of type string and “def” is an object of type string. All you managed to do was change what a was pointing to.
In fact, if you write this code:
string a = "abc"; string b = "abc";
The result is exactly the same as if you’d written:
string a = "abc"; string a = b;
Because in .NET, there is only one instance of any given string in the system. The duplicates get optimized out.
Now all of this has implications when it comes to concatenation.
Let’s say you write this code:
string a = "abc"; string b = "def"; string c = a + b;
What’s happening here?
First we create a string object that contains “abc” and point the a variable to it. Then we create another string object that contains “def” and point the b variable to it. And now this is where strings get interesting because the next thing that happens is that a NEW string object is created that contains “abcdef” and we point the c variable to that new value.
Now, if you think about this for a minute, you’ll understand that this is incredibly inefficient. Creating new objects is one of the most expensive operations that anyone can do is just about every object oriented language we have available. In fact, I can’t think of one where this is not true. I’m just assuming there must be an exception to the rule.
It would be much more efficient if we were to make string so that it wasn’t immutable. This would mean we could skip the create new object part of the assignment and our concatenation operations would work much faster.
Enter StringBuilder. StringBuilder is, essentially, the mutable version of the String class. Now you can write code that looks like this:
string a = "abc"; string b = "efg"; string c = "hij"; var d = new StringBuilder(a); d.Append(b); d.Append(c); string e = d.ToString();
Note, at the end, we still have to convert our StringBuilder object to a String object using ToString(). So, there is a new object creation penalty there. What this means is that you probably don’t want to use a StringBuilder unless you are appending to a string more than three times.
So, there you go. That’s the difference between String and StringBuilder, why a String looks like a value type, and when you should use StringBuilder instead of String.
Other post in c#
- Assign Multiple enum Values To One Variable - November 2nd, 2007
- Simple Properties in C# 3.5 - November 22nd, 2007
- CSharp adds the var keyword! - November 27th, 2007
- Object Initialization in CSharp 3.0 and VB.NET 9 - November 28th, 2007
- Computed Columns Using LINQ to SQL Classes - February 12th, 2008
- DataSets, ObjectDataSource and 3-Tier ASP.NET - February 29th, 2008
- Serializable attribute vs Serializable Interface - April 9th, 2008
- Why you can't cast an integer to a string. - June 23rd, 2008
- Unsafe Mode in C# - December 15th, 2008
- What is the global keyword in CSharp? - December 29th, 2008
- Just say “No!” to C# Regions? Really?! - April 16th, 2009
- C# “” better than string.Empty? - April 20th, 2009
- .Net String Pool – Not Just For The Compiler - April 22nd, 2009
- Upload a File via WebRequest Using CSharp - November 10th, 2009
- Azure CDN Blob Storage Case Sensitive Issue - April 17th, 2012
- && vs & and | vs ||... What's the difference? - August 21st, 2012
- Decimal vs Float (Single) or Double - September 18th, 2012
- C# Self Executing Anonymous Function - February 28th, 2013
- Dispose, Finalize and SuppressFinalize - June 12th, 2013
- CSharp Enum - October 2nd, 2013
- CSharp Numeric Overflows - July 3rd, 2014
- CSharp IDisposable Confusion - July 17th, 2014
- Why Get Certified? - July 24th, 2014
- C# Properties Get and Set - November 13th, 2014
- Value Type vs Reference Type - November 27th, 2014
- String and StringBuilder - December 11th, 2014
- Browser Automation in .NET w/ Chromium - July 9th, 2015
- CefSharp Offscreen [Why do I have so many instances of Chromium?] - October 1st, 2015