25

字符串被认为是引用类型,但可以像值一样起作用。当手动或使用 MemberwiseClone() 进行浅拷贝时,如何处理字符串?它们是否被认为是独立于副本和母版的?

4

4 回答 4

58

字符串是引用类型。但是它们是不可变的(它们不能更改),因此它们是按值复制还是按引用复制并不重要。

如果它们是浅复制的,那么引用将被复制......但你不能改变它们,所以你不能一次影响两个对象。

于 2009-02-03T10:35:00.640 回答
30

考虑一下:

public class Person
{
    string name;
    // Other stuff
}

如果您调用 MemberwiseClone,您最终会得到两个单独的 Person 实例,但它们的name变量虽然不同,但将具有相同的值 - 它们将引用相同的字符串实例。这是因为它是一个浅克隆。

如果您在其中一个实例中更改名称,则不会影响另一个,因为这两个变量本身是独立的 - 您只是更改其中一个变量的值以引用不同的字符串。

于 2009-02-03T10:46:56.793 回答
6

你只是在复制一个参考(想想“指针”);这两个引用是分开的(但恰好具有相同的值),但只有一个字符串对象。

于 2009-02-03T10:35:53.557 回答
1

@stusmith 有一个非常好的答案,乔恩提到了浅拷贝的行为。只是为了详细说明这一点,我制作了一个.NET 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
于 2020-06-23T16:13:34.163 回答