Can You Modify String Constants In C#?

Here’s an interesting question I’d like you to think about:

Is it possible to modify a string constant in C#?

So, imagine if I declare a constant string somewhere in my code, something like this:

The question is, can I add code to the Main method that will modify the contents of Sentence? Will the compiler and/or the NET Framework allow me to make this change?

Let me add another question. Assume that it is possible to change the contents of the string in Sentence. As you may know, strings are immutable in C#, meaning any change to a string automatically creates a new string on the heap while leaving the original string unmodified.

If I manage to somehow change the contents of Sentence, will this also automatically create a new string on the heap? Or can I directly access the memory where the string is stored, and change the characters in-situ?

These are interesting questions to ask because they probe how the NET Framework implements string immutability and they expose the limitations on what we can do when accessing memory directly.

Let’s find out!

Can we modify the string?

The first test is to see if we can modify the contents of Sentence. To do this, I mark the entire method as unsafe and then use the fixed keyword to obtain a pointer to the memory location where the string is stored. I store that pointer in pSentence:

Now that I have a character pointer to string memory, the actual modifying is super easy. I can’t modify pSentence directly, but I can create a new variable p, loop through every character in the string, and overwrite each character with an asterisk, like this:

So what do you think is going to happen? A compiler error? A runtime exception? Or a complete system crash?

Actually, everything is fine. Here’s the program output:

How about that? Using pointers, I can actually modify a const string variable. Everything works fine, provided I mark my method as unsafe, and use the fixed keyword to pin the string in memory and obtain a pointer to the character data.

The reason this works is because everything is an object in C#. A string constant is just another instance of the string class floating around in memory. The const keyword prevents me from modifying the variable itself, so I cannot point Sentence to another string. But I can use a char pointer to change the contents of the string itself.

Does this create a new string?

Okay, so we’ve established that it is actually possible to modify string constants in C#, using pointers. But how does this affect immutability? Did I modify the string in-situ, or did the pointer operation actually clone the string?

This is very easy to check. All I need to do is display the memory address of the string pointer before and after the modification, like this:

I am casting the char pointer to an IntPtr, which is a 64-bit integer memory address that I can write directly to the console.

Now when I run the program, the output looks like this:

And look at that – the exact same memory address, before and after the modification.

In summary

So here’s what we discovered:

      • You can directly modify string constants in C#, by using unsafe pointer operations.
      • This modifies the string in-situ, which breaks string immutability.

String immutability is actually implemented in code, in every method that modifies a string. Calling Substring or Replace or Remove simply creates a new modified string and leaves the original string unchanged. There’s no compiler or runtime magic going on to make strings immutable. It’s all manually implemented in the framework classes.

And here’s another aha moment for you: the StringBuilder class is nothing more than a wrapper for a bunch of unsafe pointer operations that modify the string directly in memory. By using the StringBuilder you get the benefit of being able to modify strings directly, without having to mark your code as unsafe.

So both classes wrap a block of memory containing character data. The String class enforces immutability, which allows you to very quickly compare strings and basically treats them as a value type. The StringBuilder class uses pointers to directly modify the character data. This breaks immutability but lets you very quickly modify strings without flooding the heap with copies.

Are you interested in C# Memory Optimization?

Click the button, and I’ll give you a coupon code for an 85% discount on my Udemy C# Memory Tricks course. You’ll get the full 3.5-hour course for only $19.

The button takes you directly to udemy.com with the coupon code already filled in.