我试图搜索我的答案并找到了关于C而不是C#的答案,所以想发布它。
我的问题可能在这里微不足道。
根据我的理解(简单来说)
复制完成后
浅拷贝 - > main和复制对象(引用或值类型)应指向内存中的同一对象
DeepCopy - > main和复制对象(引用或值类型)应指向内存中的不同对象
继续这一点,我在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
}
答案 0 :(得分: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;
}
答案 1 :(得分: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()),但会复制结构的所有字段。
值得注意的是,您对深拷贝和浅拷贝的定义与通常使用的不同。一般来说:
浅拷贝:创建了一个新的对象实例,因此所有成员都通过引用复制(例如a.X和shallowCopyOfA.X仍会引用同一个对象)。作为值类型的成员(例如结构和原语)按值复制。
深层复制:创建对象的新实例,并且还会深深复制所有成员。
答案 2 :(得分:1)
不确定您对“副本”的要求。如其他地方所述,结构在分配或传递给方法时已按值复制。那么也许你不需要额外的东西?
也许这只是你想要的东西(不确定它对任何东西是否有用!):
struct MyStruct : ICloneable
{
public int MyProperty { get; set; }
public MyStruct Clone()
{
return this;
}
object ICloneable.Clone()
{
return Clone();
}
}
警告:您的MyStruct
是一个所谓的可变结构,因为自动属性的set
访问者是公开的。许多人认为可变结构“邪恶”,因为值类型语义和可变性的组合可能导致令人惊讶的行为。
编辑:如果您想要按引用复制语义,为什么首先使用struct
而不是class
?结构不是对象的位置的引用,就像类一样。正如其他人举例说明的那样,将MyStruct
装入object
变量会使object
成为对包含MyStruct
的框的引用值。可以通过引用复制对该框的引用。
您可以创建一个只包含MyStruct
类型的实例字段的类。然后这个类将你的结构“包装”成一个引用类型,你可以通过通常的引用类型语义复制这样一个类的实例(复制引用,不复制对象本身)。
答案 3 :(得分:0)
不可能制作这么浅的结构副本。
考虑改用类。