2

当我尝试分配给字符串中的单个字符时,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"
4

5 回答 5

7

这:

s="acc"

...正在更改变量的值以引用不同的字符串。如果允许:

s[0] = 'a';

这不会改变变量的值——它必须改变所s引用的字符串的内容。字符串在 .NET 中是不可变的,因此这是不允许的。

区分更改变量的值和更改它所引用的对象中的数据很重要。

更改的内容s.ToCharArray()不会对字符串s 字符串做任何事情 - 它只会改变新创建的数组,该数组是字符串中数据的副本

于 2013-02-12T08:20:30.097 回答
3

来自MSDN

字符串是不可变的——字符串对象的内容在创建对象后不能更改,尽管语法使它看起来好像您可以这样做。例如,当您编写此代码时,编译器实际上会创建一个新的字符串对象来保存新的字符序列,并将该新对象分配给 b。然后字符串“h”就可以进行垃圾回收了。

s.ToCharArray()正在将字符串的内容复制到数组中。但是你不能修改这个字符串引用中的第一个字符——这个字符串本身永远不会改变。

于 2013-02-12T08:21:17.517 回答
2

字符串在 .NET 中实现为写时复制(更准确地说:基于字符串池)和引用类型。您要做的是获取构成字符串的基础 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"; 
}

这就是字符串被实现为不可变的原因:保护对字符串的引用不被获取不同的内容。

另请参阅此处以了解字符串池的行为。

于 2013-02-12T08:20:59.773 回答
0

不能s[0]直接比较s.ToCharArray()[0]

随着s[0]您尝试访问 String 对象的第一个元素。

s.ToCharArray()返回一个字符数组,例如 c[N]。有了这个,您可以访问第 0 个定位元素。

并且随着s = "pqr";您更改对象 s 指向的字符串值。

于 2013-02-12T08:20:39.383 回答
0

这个答案不是为了解释这个readonly问题,而是如果你想修改char索引的基础。

        var s = "bcc".ToCharArray();
        s[0] = 'a';
        Console.WriteLine(s[0].ToString());
于 2013-02-12T08:37:50.417 回答