当我尝试使用s[i] = c
分配给字符串中的单个字符时,我收到编译错误:
string s = "bcc";
s[0] = 'a'; // shows compile time error - indexer cannot be assigned - it's readonly
然而这有效:
s.ToCharArray()[0] = 'a';
我们也可以将字符串完全分配给acc
:
s = "acc"
答案 0 :(得分:4)
此:
s="acc"
...正在更改变量的值以引用不同的字符串。如果允许的话:
s[0] = 'a';
不会改变变量的值 - 它必须改变s
引用的字符串的内容。字符串在.NET中是不可变的,所以这是不允许的。
区分更改变量的值和更改其引用的对象内的数据非常重要。
更改s.ToCharArray()
的内容对s
或字符串没有任何作用 - 它只是改变了新创建的副本数组字符串中的数据。
答案 1 :(得分:3)
来自MSDN:
字符串是不可变的 - 创建对象后无法更改字符串对象的内容,尽管语法使其看起来好像可以执行此操作。例如,当您编写此代码时,编译器实际上会创建一个新的字符串对象来保存新的字符序列,并将该新对象分配给b。然后字符串“h”有资格进行垃圾收集。
s.ToCharArray()
正在将字符串的内容复制到数组中。但是你不能修改这个字符串引用中的第一个字符 - 这个字符串本身永远不会改变。
答案 2 :(得分:2)
一个字符串在.NET中实现为copy-on-write(更确切地说:基于字符串池)和reference-type。你要做的是获取构成字符串的底层char []并进行更改。但是,由于string
是作为写时复制实现的,如果要成功,你不会只改变一个字符串而是改变所有字符串。
例如,如果您的代码更改字符串会发生这种情况:(以说明不正确的假设):
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'?
当你尝试它时,t将是'foo',因为底层内容保持不变。 ToCharArray制作基础内容的副本,从而保护底层内容,以便不会影响对同一字符串对象的其他引用。
这也是这样的代码不好的原因:
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";
}
这就是为什么字符串被实现为不可变的原因:保护对字符串的引用以获取不同的内容。
另请参阅here有关字符串池的行为。
答案 3 :(得分:0)
您无法直接将s[0]
与s.ToCharArray()[0]
进行比较。
使用s[0]
,您正在尝试访问String对象的第一个元素。
s.ToCharArray()
返回一个字符数组,表示c [N]。有了这个,您可以访问第0个定位元素。
使用s = "pqr";
,您正在更改对象s所指向的字符串值。
答案 4 :(得分:0)
这个答案不是要解释readonly
问题,而是要修改索引的char
基础。
var s = "bcc".ToCharArray();
s[0] = 'a';
Console.WriteLine(s[0].ToString());