关于C#字符串的问题:不可抗力和克隆

我正在阅读Accelerated C#2010。并提出几个问题

问题1

String的实例是不可变的,因为一旦你创建它们,你就无法改变它们

怎么回事呢。 我有一段时间没有使用过C#,加上我刚刚开始,所以即使在语法上我也许错了。

string str1 = "this is a string"; // i hope my syntax is right str1 = "this is a NEW string"; // i think i can do this right? 

问题2

如果在字符串上调用ICloneable.Clone方法,则会得到一个指向与源相同的字符串数据的实例。 实际上,ICloneable.Clone只是返回对此的引用

如果这是真的,那就意味着

 string str1 = "string 1"; // i hope my syntax is right too. i am really not sure about this string str2 = str1.Clone(); str2 = "modified string"; // will str1 be modified too? 

 string str1 = "this is a string"; // i hope my syntax is right str1 = "this is a NEW string"; // i think i can do this right? 

当然! string是一个引用类型(一个指针 ,如果你想这样看就像这样),所以在第2行,你将变量str1指向内存中的另一个 (常量)字符串。 原始字符串不会更改,它不再被引用。

 string str1 = "string 1"; string str2 = str1.Clone(); // i hope my syntax is right too. i am really not sure about this str2 = "modified string"; // will str1 be modified too? 

不,因为你没有修改"string 1" 。 在第2行之后,它看起来像这样:

 memory "string 1" ^ ^ | | stack str1 str2 

在第3行之后,它看起来像这样:

 memory "string 1" "modified string" ^ ^ | | stack str1 str2 

这里的共识答案是正确的。

字符串类型是内存中不可变字符串的引用类型。 所有字符串的集合都在内存中创建(恰当地称为字符串池),其中包含您创建的字符串。 在问题1中,您的第一个语句在内存中创建一个字符串,并为str1分配对字符串池中该字符串的引用。

当您执行以下操作时

 str1 = "this is a NEW string"; 

您实际上是在字符串池中添加一个新字符串(透明地创建一个新字符串),然后为str1分配一个对新字符串的引用。

考虑一下,例如:

 string str1 = "this is my old string"; str1 = "this is my NEW string"; str1 = "this is my old string"; 

在这种情况下,只在字符串池中创建两个字符串。 当您到达代码中的第三行时,.NET平台会检查字符串池,找到匹配项,并为str1提供对已存在的字符串池中字符串的引用,而不是创建重复项。

为了推动这一点,让我们这样做:

 string str1 = "this is a string"; string str2 = "this is a string"; //both strings have a reference to the same string in memory str1 = str1.Replace("this","xxxx"); 

想想这里发生了什么。 str1和str2引用了字符串池中的相同字符串。 str1.Replace()实际上并没有改变字符串池中的现有字符串(如果是,str1 AND str2将具有新值),而是创建一个新字符串,然后为str1分配对它的引用。

字符串是不可变的,一旦它们存在于内存中 ,它们就不能被改变。 C#中的StringBuilder允许我们避免这个问题。 我们可以自由地修改StringBuilder对象中的内容。 在我们调用.ToString()方法之前,我们创建的字符串不会提交给字符串池。

您指的是对字符串的引用 。 那些确实是可变的。 请记住,字符串是引用类型

这就是你可以改变字符串变量赋值的原因。

然而,实际上尝试改变字符串的内容是困难的,至少可以说(这不是不可能的,但是对于所有意图和目的,应该被认为是这样)。

这就是为什么对字符串执行操作的字符串上的所有方法(Trim,ToUpper等等)返回字符串; 调用该方法的原始方法是不可变的。

问题1:正确,如果这不是所需的function,请查看StringBuilder对象。

问题2:不,克隆返回对原始字符串的引用。 将对新指针str2引用的内存进行任何修改。