1

我试图搜索我的答案,发现它们是关于 C 而不是 C#,所以想到发布它。

我的问题在这里可能是微不足道的。

根据我的理解(简单来说)

复制完成后

浅拷贝 -> 主对象和拷贝对象(引用或值类型)应该指向内存中的同一个对象

DeepCopy -> 主对象和复制对象(引用或值类型)应该指向内存中的不同对象

继续进行此操作,我在 C# 中有一个结构,并尝试对其进行浅拷贝。我尝试使用“MemberwiseClone”方法,但我猜它只适用于引用类型。对于值类型,我认为“MemberwiseClone”方法会将其装箱到一个对象中,然后将其拆箱到堆栈中的不同内存地址中。

我尝试过的如下。

我的问题是如何(如果可能的话)创建一个简单结构的浅表副本?

我希望我的基本原理在这里是正确的,而不是胡说八道。如果我在我所做的任何陈述中有错误,请纠正我。

问候,

萨马尔

struct MyStruct : ICloneable
{
    public int MyProperty { get; set; }

    public object Clone()
    {
        return this.MemberwiseClone();//boxing into object
    }
}


    private void btnChkStr_Click(object sender, EventArgs e)
    {
        MyStruct struct1 = new MyStruct();
        struct1.MyProperty = 1;

        //MyStruct struct2 = struct1; //This will create a deep copy
        MyStruct struct2 = (MyStruct)(struct1.Clone());//unboxing into structure hence allocating a different memory address
        struct2.MyProperty = 2;

        MessageBox.Show(struct1.MyProperty.ToString()); //still showing 1
    }
4

4 回答 4

5

你对深拷贝和浅拷贝的期望是不正确的。浅拷贝复制所有的值类型,并且只复制引用类型的引用。深拷贝复制所有值类型和所有引用类型。

因此,您的结构在执行以下操作时已经执行了浅拷贝:

MyStruct struct2 = struct1;

此代码示例(控制台应用程序)显示,更改第二个结构中对象的值也会更改第一个结构中对象的值,因为该对象刚刚通过引用复制:

class Program
{
    static void Main(string[] args)
    {
        Test t1 = new Test();
        t1.i = 1;
        t1.o = new Klasse();
        t1.o.i = 1;

        Test t2 = t1;
        t2.i = 2;
        t2.o.i = 2;

        Console.WriteLine(t1.i.ToString());
        Console.WriteLine(t1.o.i.ToString());
        Console.WriteLine(t2.i.ToString());
        Console.WriteLine(t2.o.i.ToString());
        Console.Read();
    }
}

struct Test
{
    public int i;
    public Klasse o;
}

class Klasse
{
    public int i = 0;
}
于 2013-08-02T09:37:32.573 回答
2

您可以通过显式装箱结构来实现对浅拷贝的定义。但是,由于结构是装箱的,因此访问它的属性并不容易!

void Main()
{
    object o1 = new M { A = 1 };
    object o2 = o1;

    // o2.A = 100 (this can also be done using dynamic)
    var prop = typeof(M).GetProperty("A");
    prop.SetValue(o2, 100);

    // prints 100, since both point to the same instance
    Console.WriteLine(((M)o1).A);
}

public struct M {
    public int A { get; set; }
}

通常,虽然将结构分配给新变量(或调用 MemberwiseClone()),但会复制结构的所有字段。

还值得注意的是,您对深拷贝和浅拷贝的定义与通常使用的不同。一般来说:

浅拷贝:创建对象的一个​​新实例,因此它的所有成员都通过引用进行复制(egaX 和 shallowCopyOfA.X 仍将引用同一个对象)。作为值类型的成员(例如结构和原语)按值复制。

深拷贝:对象的一个​​新实例被创建,所有成员也被深拷贝。

于 2013-08-02T09:29:39.300 回答
1

不确定您对“副本”的要求。如其他地方所述,结构在分配或传递给方法时已经按值复制。所以也许你不需要额外的东西?

也许这正是您想要的(不确定它是否对任何事情有用!):

struct MyStruct : ICloneable
{
    public int MyProperty { get; set; }

    public MyStruct Clone()
    {
        return this;
    }
    object ICloneable.Clone()
    {
        return Clone();
    }
}

一个警告:MyStruct是一个所谓的可变结构,因为set自动属性的访问器是公共的。许多人认为可变结构是“邪恶的”,因为值类型语义和可变性的结合会导致令人惊讶的行为。

编辑:如果您想要按引用复制语义,为什么首先使用 astruct而不是 a class?结构不是对对象位置的引用,就像类一样。正如其他人给出的示例一样,将其装箱MyStructobject变量中将使该变量成为对包含该值的object的引用。可以通过引用复制对框的引用。MyStruct

您可以创建一个仅包含一个类型为 的实例字段的类MyStruct。然后这个类将你的结构“包装”成一个引用类型,你可以通过通常的引用类型语义复制这样的类的实例(复制引用,对象本身不被复制)。

于 2013-08-02T09:31:15.077 回答
0

制作这样一个结构的浅拷贝是不可能的。

考虑改用类。

于 2013-08-02T09:24:14.593 回答