2

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"
2
  • 3
    Strings are immutable in .NET. Arrays are generally not. Commented Feb 12, 2013 at 8:19
  • 2
    "this works", only insofar as there is no compiler or runtime error. The value of s is unchanged. Commented Feb 12, 2013 at 8:32

5 Answers 5

7

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.

Sign up to request clarification or add additional context in comments.

Comments

3

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.

Comments

3

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.

2 Comments

It seems I'm unable to explain what I mean. According to what I can read in reflector it is copy-on-write (well, with a stringpool that is), which means changing ch[0] would make all references corrupt - which would be a disaster. I'm trying to explain what would happen if his code would alter the string, I know that it doesn't change 'foo' into 'boo'... let me see if I can modify my answer
@leppie here, sorry for not being a native english speaker... I hope this covers the point I was trying to make better?
0

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.

Comments

0

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());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.