Igoy
Igoy

Reputation: 2962

Why is the indexer for strings readonly?

When I try to assign to individual characters in a string with s[i] = c I get a compiler error:

string s = "bcc";
s[0] = 'a'; // shows compile time error - indexer cannot be assigned - it's readonly

However this works:

s.ToCharArray()[0] = 'a';

and we can also completely assign the string to acc:

s = "acc"

Upvotes: 2

Views: 9491

Answers (5)

atlaste
atlaste

Reputation: 31116

A string is in .NET implemented as copy-on-write (more exactly: based on a string pool) and as reference-type. What you're trying to do is get the underlying char[] that makes up the string and change that. However, since string is implemented as copy-on-write, if that were to succeed, you wouldn't just change one string but all of them.

For example, this is what would happen if your code would change the string: (to illustrate the incorrect assumption):

string s = "foo"; // create instance with foo
string t = s;     // copy reference, contents aren't changed
char[] ch = s.ToCharArray(); // attempt to access underlying contents
ch[0] = 'b';      // attempts to change the underlying contents
Console.WriteLine(t); // 'boo'?

When you try it, t will be 'foo', because the underlying contents remain intact. ToCharArray makes a copy of the underlying contents, thereby protecting the underlying contents so that other references to the same string object are not affected.

This is also the reason code like this is a bad practice:

string s = "";
for (int i=0; i<10000; ++i) 
{
    // makes a new instance of the string, copies the contents 
    // and appends a single char... as you can see 10K times...
    s = s + "a"; 
}

This is why strings are implemented as immutable: to protect references to a string from getting different content.

See also here about the behavior of the string pool.

Upvotes: 3

spajce
spajce

Reputation: 7082

This answer is not to explain about the readonly issue but if you want to modify the char base on the index.

        var s = "bcc".ToCharArray();
        s[0] = 'a';
        Console.WriteLine(s[0].ToString());

Upvotes: 0

Yaakov Ellis
Yaakov Ellis

Reputation: 41500

From MSDN:

Strings are immutable--the contents of a string object cannot be changed after the object is created, although the syntax makes it appear as if you can do this. For example, when you write this code, the compiler actually creates a new string object to hold the new sequence of characters, and that new object is assigned to b. The string "h" is then eligible for garbage collection.

s.ToCharArray() is copying the contents of the string to an array. But you cannot modify the first character in this string reference - this string itself will never change.

Upvotes: 3

mihirj
mihirj

Reputation: 1219

You cannot compare s[0] directly with s.ToCharArray()[0].

With s[0] you are trying to access first element of String object.

s.ToCharArray() returns an array of characters say c[N]. With this you can access 0th positioned element.

And with s = "pqr"; you are changing the string value to which object s is pointing.

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500595

This:

s="acc"

... is changing the value of the variable to refer to a different string. If this were allowed:

s[0] = 'a';

that wouldn't be changing the value of the variable - it would have to change the contents of the string that s referred to. Strings are immutable in .NET, so that's not allowed.

It's important to differentiate between changing the value of a variable and changing the data within the object it refers to.

Changing the contents of s.ToCharArray() doesn't do anything to either s or the string - it just mutates the newly-created array which is a copy of the data within the string.

Upvotes: 7

Related Questions