何时复制C#值/对象以及何时复制其引用?

时间:2010-12-03 16:58:13

标签: c# reference copy equals-operator

我一遍又一遍地得到同样的问题,我想要引用的对象被复制,或者我想要复制的对象被引用。当我使用=运算符时会发生这种情况。

例如,如果我将对象发送到另一个表单,即:

SomeForm myForm = new SomeForm();
SomeObject myObject = new SomeObject();
myForm.formObject = myObject;

...然后在表单中修改对象,原始对象不会被修改。就好像复制了对象而没有引用对象。然而,当我这样做时:

SomeObject myObject = new SomeObject();
SomeObject anotherObject = new SomeObject();
anotherObject = myObject;

...然后修改anotherObjectmyObject也会被修改。

最严重的情况是当我尝试克隆我定义的一个对象时:

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关键字,何时复制对象以及何时在每种情况下引用对象(即传递给函数时)当设置为其他对象时(如上面的前两个例子),复制成员变量时,如第三个例子等)?

3 个答案:

答案 0 :(得分:45)

如果不花费大量时间仔细挑选你的话,很难回答这类问题。

我已经在一些您认为有用的文章中这样做了:

这并不是说这些文章是完美的 - 当然 - 远非如此 - 但我已经尽力了。

我认为一个重要的事情是将两个概念(参数传递和参考与值类型)分开来。

查看您的具体示例:

SomeForm myForm = new SomeForm();
SomeObject myObject = new SomeObject();
myForm.formObject = myObject;

这意味着myForm.formObjectmyObject引用SomeObject的相同实例 - 就像两个人有单独的纸张一样,每个人都有相同的地址。如果你去一张纸上的地址并把房子漆成红色,那么去第二张纸上的地址,你会看到一个红房子。

您不清楚“然后修改表单中的对象”是什么意思,因为您提供的类型是不可变的。没有办法修改对象本身。您可以更改myForm.formObject以引用SomeObject的其他实例,但这就像在一张纸上涂写地址并在其上写一个不同的地址一样。这不会改变另一篇论文上的内容。

如果您可以提供一个简短但完整的程序,其行为您不理解(理想情况下是一个控制台应用程序,只是为了让事情变得更简单和更简单),那么在具体内容中讨论事情会更容易术语

答案 1 :(得分:6)

迈克,你好 从ValueType派生的所有对象(例如struct或其他基元类型)都是值类型。这意味着只要将它们分配给变量或将它们作为方法参数传递,就会复制它们。其他类型是引用类型,这意味着,当您将引用类型分配给变量时,不是它的值,而是将其在内存空间中的地址分配给变量。 另外,您应该注意,您可以使用ref关键字将值类型作为引用传递。这是语法

public void MyMethod(ref int a) { a = 25 }
int i = 20;
MyMethod(ref i); //Now i get's updated to 25.

希望有所帮助:)

答案 2 :(得分:1)

关于克隆对象,如果从一个对象复制到另一个对象的值是引用类型,那么对原始对象中这些值的任何修改都会影响复制对象中的值(因为它们只是对它们的引用)对象)

如果您需要克隆具有引用类型属性的对象,则需要使这些类型可克隆,或者通过根据需要实例化新实例来手动复制它们。

考虑使用IClonable界面虽然它不是最好的解决方案imho。