1

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.objy 的值吗?由于 obj 是一个System.Object显然是引用类型的实例。但它不会改变 -obj1.obj给出 x 并obj2.obj给出 y。为什么是这样?

4

2 回答 2

2

这是因为你没有改变 field 的状态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
}
于 2012-11-11T07:19:35.573 回答
1
  1. 您的代码包含 3 个语法错误(无法运行)

  2. 考虑您的代码:

    公共静态无效 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();
    }
}
于 2020-12-15T15:45:18.200 回答