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

问题描述 投票:0回答:3

在复制我要引用的对象或引用我要复制的对象时,我不断遇到相同的问题。当我使用 = 运算符时会发生这种情况。

例如,如果我将对象发送到另一种形式,即:

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
等系统对象似乎总是被复制,除了上面的clone方法。

我的问题是,不考虑在函数中使用

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

c# reference copy equals-operator
3个回答
66
投票

如果不花费大量时间仔细挑选措辞,就很难准确回答此类问题。

我在几篇文章中这样做了,您可能会觉得有用:

当然,这并不是说这些文章是完美的 - 远非如此 - 但我已尽力表达清楚。

我认为一件重要的事情是在你的头脑中区分两个概念(参数传递和引用与值类型)。

看你的具体例子:

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

这意味着

myForm.formObject
myObject
指的是
SomeObject
的同一个实例 - 就像两个人拥有不同的纸,每个人都写有相同的地址。如果你去一张纸上的地址,把房子涂成红色,然后去第二张纸上的地址,你会看到一栋红色的房子。

不清楚“然后修改表单中的对象”是什么意思,因为您提供的类型是不可变的。没有办法修改对象本身。您可以更改

myForm.formObject
以引用
SomeObject
的不同实例,但这就像在一张纸上潦草地写下地址,然后在上面写一个不同的地址。这不会改变另一张纸上写的内容。

如果您可以提供一个简短但完整的程序,其行为您不理解(最好是控制台应用程序,只是为了让事情变得更短更简单),那么具体地讨论事情会更容易。


11
投票

嗨迈克 所有派生自 ValueType 的对象(例如结构体或其他基本类型)都是值类型。这意味着每当您将它们分配给变量或将它们作为方法参数传递时,它们都会被复制。其他类型是引用类型,这意味着,当您将引用类型分配给变量时,分配给该变量的不是它的值,而是它在内存空间中的地址。 您还应该注意,您可以使用 ref 关键字将值类型作为引用传递。这是语法

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

希望有帮助:)


1
投票

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

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

考虑使用 IClonable 界面,但恕我直言,它不是最好的解决方案。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.