Tech Off Post

Single Post Permalink

View Thread: Why are string types immutable in C#?
  • User profile image
    Sven Groot

    Manip, although you are correct, this has nothing to do with why the String object is immutable. If I append a few characters to a StringBuilder, the same move/copy/free thing is done, but the StringBuilder class is not immutable.

    Let's take a look at an example with a method that both the StringBuilder and String classes have:

    String x = "hello";
    String y = x.Replace('e', 'u');
    StringBuilder a = new StringBuilder("hello");
    StringBuilder b = a.Replace('e', 'u');
    Console.WriteLine("x: " + x);
    Console.WriteLine("y: " + y);
    Console.WriteLine("a: " + a.ToString());
    Console.WriteLine("b: " + b.ToString());

    What's the output of this program:
    x: hello
    y: hullo
    a: hullo
    b: hullo

    As you can see, the Replace call did not change the String class instance, but it did change the StringBuilder instance (the only reason why StringBuilder.Replace also returns an instance is to make it possible to chain calls. In fact, it doesn't return a new instance, but the same one, so you'll find that Object.ReferenceEquals(a, b) == true).

    Now as to why. I don't know all the reasons, but one of them is this. In .Net, String is a reference type, so it is never copied, but passed by reference. Compare this to the C++ std::string object (which is not immutable), which is passed by value. This means that if you want to use a String as a key in a Hashtable, you're fine in C++, because C++ will copy the string to store the key in the hashtable (actually std::hash_map, but still) for later comparison. So even if you later modify the std::string instance, you're fine.

    But in .Net, when you use a String in a Hashtable, it will store a reference to that instance. Now assume for a moment that strings aren't immutable, and see what happens:
    1. Somebody inserts a value x with key "hello" into a Hashtable.
    2. The Hashtable computes the hash value for the String, and places a reference to the string and the value x in the appropriate bucket.
    3. The user modifies the String instance to be "bye".
    4. Now somebody wants the value in the hashtable associated with "hello". It ends up looking in the correct bucket, but when comparing the strings it says "bye"!="hello", so no value is returned.
    5. Maybe somebody wants the value "bye"? "bye" probably has a different hash, so the hashtable would look in a different bucket. No "bye" keys in that bucket, so our entry still isn't found.

    Making strings immutable means that step 3 is impossible. If somebody modifies the string he's creating a new string object, leaving the old one alone. Which means the key in the hashtable is still "hello", and thus still correct.

    So, probably among other things, immutable strings are a way to enable strings that are passed by reference to be used as keys in a hashtable or similar dictionary object.