【问题标题】:memberwiseclone in C# - system.objectC# 中的 memberwiseclone - system.object
【发布时间】:2012-10-31 00:34:09
【问题描述】:

MemberwiseClone() 将创建浅拷贝,它将对值类型进行逐位拷贝,并且只拷贝引用类型的引用。我们需要创建一个深层副本以拥有引用类型的独立副本。还行吧。我明白了。 现在我的问题是:为什么在调用 MemberwiseClone() 时 System.Object 变量的反应不同?

例如:

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。这是为什么呢?

【问题讨论】:

  • @Michael,感谢您的编辑。请回答我的问题,任何帮助将不胜感激。

标签: c# clone


【解决方案1】:

这是因为您没有更改字段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
}

【讨论】:

  • 感谢回答的朋友。但是请您简要解释一下。现在 obj 也不再是引用类型了?与 List 作为字符串是值类型?
  • @Zodiac, List&lt;&gt; 是引用类型,不管它是否包含值类型列表
  • @Zodiac,Jon Skeet 的文章中有很好的解释:yoda.arachsys.com/csharp/references.html
  • @2kay,我想我明白了,当我将 obj 显式转换为 list 时,我已将其设置为 refrence 类型,现在 obj1.obj 和 ob2.obj 都将指向同一个对象。但是为什么当我们直接分配它时不会发生这种情况。当我执行 obj1.obj = "X" 时,它是否将 obj 视为此处的值类型?好像是的
  • 感谢@Furqan,为您解决这个问题。如果可以的话,请说明我对 2kay 的问题。谢谢朋友
【解决方案2】:
  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();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-29
    • 2014-06-24
    相关资源
    最近更新 更多