何时复制C#值/对象,何时复制其引用?
我不断地得到相同的问题,我想要引用的对象被复制或我想要复制的对象被引用的地方。 当我使用=运算符时会发生这种情况。
例如,如果我将对象发送给另一个表单,即:
SomeForm myForm = new SomeForm(); SomeObject myObject = new SomeObject(); myForm.formObject = myObject;
…然后修改表单中的对象,原始对象不会被修改。 就好像该对象被复制并且没有被引用。 然而,当我这样做时:
SomeObject myObject = new SomeObject(); SomeObject anotherObject = new SomeObject(); anotherObject = myObject;
…然后修改anotherObject
, myObject
也会被修改。
最令人烦恼的情况是,当我尝试克隆我定义的对象之一:
public class SomeObject { double value1, value2; //default constructor here public SomeObject(val1, val2) { value1 = val1; value2 = val2; } public void Clone(SomeObject thingToCopy) { this.value1 = thingToCopy.value1; this.value2 = thingToCopy.value2; } }
当我这样做…
SomeObject obj1 = new SomeObject(1, 2); SomeObject obj2 = new SomeObject(); obj2.Clone(obj1);
… obj1
被引用,任何对obj2
修改都会改变obj1
。
像int, double, string
等系统对象似乎总是被复制,除了上面的克隆方法。
我的问题是,没有考虑到在函数中使用ref
关键字,什么时候一个对象被复制,什么时候一个对象被引用,在任何情况下(即当传递给函数,当设置为其他对象时上面的前两个例子),复制类似第三个例子的成员variables等)?
没有花费大量的时间仔细地select你的话,很难回答这样的问题。
我已经在几篇文章中这样做了,您可能会发现它们很有用:
- 在C#/ .NET中传递的参数
- C#/ .NET中的引用types和值types
当然,这并不是说这些文章是完美的 – 远非如此 – 但是我尽可能地尽量清楚。
我认为重要的是将两个概念(parameter passing和参考与值types)分开。
看看你的具体例子:
SomeForm myForm = new SomeForm(); SomeObject myObject = new SomeObject(); myForm.formObject = myObject;
这意味着myForm.formObject
和myObject
引用了SomeObject
的同一个实例 – 就像两个人分开的纸一样,每个人都有相同的地址。 如果你去一张纸上的地址,把房子涂成红色,然后到第二张纸上的地址,你会看到一个红色的房子。
不清楚你的意思是什么,然后修改表单中的对象,因为你提供的types是不可变的。 没有办法修改对象本身。 您可以将myForm.formObject
更改为引用myForm.formObject
的另一个实例,但这就像在一张纸上SomeObject
地址并在其上写入不同的地址。 这不会改变在另一张纸上写的东西。
如果你可以提供一个简短但完整的程序,其行为你不理解(最好是一个控制台应用程序,只是为了使事情变得简短而简单),用具体的术语来谈论事情会更容易一些。
您好迈克从ValueType派生的所有对象,如结构或其他基元types是值types。 这意味着只要您将它们分配给variables或将其作为方法parameter passing,就会将其复制。 其他types是引用types,这就意味着,当你把一个引用types分配给一个variables时,不是它的值,而是把它在内存空间中的地址赋值给variables。 你也应该注意到你可以使用ref关键字来传递一个值types作为参考。 这是语法
public void MyMethod(ref int a) { a = 25 } int i = 20; MyMethod(ref i); //Now i get's updated to 25.
希望能帮助到你 :)
关于克隆你的对象,如果你从一个对象复制到另一个对象的值是引用types,那么对原始对象中的这些值的任何修改将影响复制对象中的值(因为它们只是对同一对象的引用)
如果需要克隆具有引用types属性的对象,则需要使这些types可克隆,或者根据需要通过实例化新实例来手动复制这些types。
考虑使用IClonable接口,虽然它不是最好的解决scheme。