在C#中浅复制时,字符串是如何工作的?

25

字符串被视为引用类型,但可以像值类型一样使用。当手动复制或使用MemberwiseClone()进行浅复制时,字符串如何处理?它们是否与副本和主对象分开且独立?

4个回答

62

字符串是引用类型。但是它们是不可变的(不能被更改),因此无论按值复制还是按引用复制都无关紧要。

如果浅复制它们,则将复制引用... 但您无法更改它们,因此无法同时影响两个对象。


所以当我更改副本对象中的字符串时,会创建一个新的字符串并具有新的引用吗?所以当我像 oldString = oldString + "A" 这样做时,我正在创建一个具有新引用的新对象? - danmine
3
这也解释了为什么 String.Replace 必须返回一个新的字符串,而不是改变原来的字符串。 - stusmith
如果您需要一个可变字符串,请考虑使用 StringBuilder。 - stusmith
我每天学到新东西。这解答了我许多有关字符串的问题。 - danmine
8
这是否意味着对仅包含字符串成员的对象执行浅复制是可以的? - Dan Stevens

30

考虑以下内容:

public class Person
{
    string name;
    // Other stuff
}
如果你调用MemberwiseClone,你将得到两个不同的Person实例,但是它们的name变量,虽然是不同的,但是它们会引用相同的字符串实例。这是因为这是一个浅克隆。
如果你改变其中一个实例的name,那么不会影响另一个实例,因为两个变量本身是独立的 - 你只是改变其中一个变量的值,使其引用不同的字符串。

5
你只是在复制一个引用(类似于“指针”);这两个引用是独立的(但恰巧具有相同的值),但只有一个字符串对象。

1

@stusmith有一个非常好的答案,jon提到了浅拷贝的行为。只是为了更详细地说明这一点,我做了一个.NET Fiddle

你会注意到我做了一个浅拷贝,但实际上,由于唯一的成员是一个字符串,它也起到了深拷贝的作用。要明确的是,在引用字符串的意义上,它并不是深拷贝,因此当运行复制函数时,存在两个对象在内存中引用同一个字符串。

然而,对于许多应用程序来说,这是可以接受的,就像在我的例子中一样,当我在复制第一个对象之后更新字符串时,会创建一个新的字符串和引用,因此最终结果是具有对不同字符串值的不同引用的两个对象。

这里是fiddle正在执行的预览:

// Create a person
Person a = new Person("Sally");

// Shallow copy the person
Person b = a.ShallowCopy();

// Change the name of the second person
b.firstName = "Bob";

// Observe that the original person's name has not changed
Console.WriteLine("First person is {0}", a.firstName);
Console.WriteLine("Second person is {0}", b.firstName);

// Output is:
// First person is Sally
// Second person is Bob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接