字符串被认为是引用类型,但可以像值一样。当浅层手动或使用MemberwiseClone()复制某些内容时,如何处理字符串?它们是否被分开并与副本和主人隔离?
答案 0 :(得分:46)
字符串ARE引用类型。但是它们是不可变的(它们不能被更改),所以如果它们按值复制或通过引用复制它们并不重要。
如果它们被浅层复制,那么将复制引用...但是您无法更改它们,因此您不能同时影响两个对象。
答案 1 :(得分:24)
考虑一下:
public class Person
{
string name;
// Other stuff
}
如果你调用MemberwiseClone,你最终会得到两个单独的Person实例,但是它们的name
变量虽然不同,但它们具有相同的值 - 它们将引用相同的字符串实例。这是因为它是一个浅层克隆。
如果更改其中一个实例中的名称,那么这不会影响另一个实例,因为这两个变量本身是分开的 - 您只是更改其中一个变量的值以引用不同的字符串。
答案 2 :(得分:6)
您只是复制引用(想想“指针”);这两个引用是分开的(但碰巧具有相同的值),但只有一个字符串对象。
答案 3 :(得分:0)
@stusmith有一个非常好的答案,乔恩(Jon)提到了浅表副本的行为。为了详细说明,我做了一个.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