MemberwiseClone()
将创建浅拷贝,它将对值类型进行逐位复制,并仅复制引用类型的引用。我们需要创建一个深层副本以获得引用类型的独立副本。还行吧。我明白了
现在我的问题是:为什么System.Object
变量在调用MemberwiseClone()时会有不同的反应?
例如:
Public class Test
{
public int x;
public object obj;
public Test MyClone()
{
return (Test) this.MemberwiseClone();
}
}
现在在我的Main方法中访问它:
public static void Main()
{
Test obj1 = new obj1;
obj1.x = 1;
obj1.obj = "x";
Test obj2 = obj1.MyClone();
obj2.obj = "y"
}
这不应该将obj1.obj
的值更改为y吗?由于obj是System.Object
的一个实例,它显然是一个引用类型。但它不会改变 - obj1.obj
给出x而obj2.obj
给出y。这是为什么?
答案 0 :(得分:2)
这是因为您没有更改字段obj
的状态。你分配它。
public static void Main()
{
Test obj1 = new obj1;
obj1.x = 1;
obj1.obj = new List<string> {"x"};
Test obj2 = obj1.MyClone();
((List<string>) obj2.obj).Add("y"); //now it contains {x, y} in obj1 and obj2
}
答案 1 :(得分:0)
您的代码包含3个语法错误(无法运行)
考虑您的代码:
public static void Main() { 测试obj1 =新的obj1; obj1.x = 1; obj1.obj =“ x”;
Test obj2 = obj1.MyClone();
obj2.obj = "y"
}
您的错误思考位于这里:
obj2.obj = "y"
这不会更改obj的值,它会关联一个与非克隆实例无关的其他字符串对象。
这是因为每个字符串都是不可变的对象。不同的字符串会导致堆上的对象不同。
但是如果您设法实际上更改字符串内容小精灵,那么您将获得预期的效果。
使用不安全模式,您可以通过以下方式证明这一点:
using System.Diagnostics;
static class Program
{
static void Main()
{
Test obj1 = new Test();
obj1.x = 1;
obj1.obj = "abc";
Test obj2 = obj1.MyClone();
var obj1Str = obj1.obj as string;
ReverseString(obj1Str);
var obj2Str = obj2.obj as string;
Debug.Print(obj2Str); // "cba"
}
static unsafe void ReverseString(string str)
{
int i = 0;
int j = str.Length - 1;
fixed (char* fstr = str)
while (i < j)
{
char temp = fstr[j];
fstr[j--] = fstr[i];
fstr[i++] = temp;
}
}
}
public class Test
{
public int x;
public object obj;
public Test MyClone()
{
return (Test)MemberwiseClone();
}
}