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

Mik*_*ebb 66 c# copy reference equals-operator

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

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

SomeForm myForm = new SomeForm();
SomeObject myObject = new SomeObject();
myForm.formObject = myObject;
Run Code Online (Sandbox Code Playgroud)

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

SomeObject myObject = new SomeObject();
SomeObject anotherObject = new SomeObject();
anotherObject = myObject;
Run Code Online (Sandbox Code Playgroud)

...然后修改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;
    }
}
Run Code Online (Sandbox Code Playgroud)

当我这样做的时候......

SomeObject obj1 = new SomeObject(1, 2);
SomeObject obj2 = new SomeObject();
obj2.Clone(obj1);
Run Code Online (Sandbox Code Playgroud)

... obj1被引用以及对obj2更改的任何修改obj1.

int, double, string似乎总是复制诸如等的系统对象,除了上面的克隆方法.

我的问题是,没有考虑ref在函数中使用关键字,何时复制对象以及何时在每种情况下引用对象(即当传递给函数时,设置为其他对象时(如前两个例子),当复制成员变量时,如第三个例子,等等)?

Jon*_*eet 48

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

我在几篇你可能会觉得有用的文章中这样做过:

这并不是说文章是完美的,当然 - 远非如此 - 但我试图尽可能清楚.

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

要查看您的具体示例:

SomeForm myForm = new SomeForm();
SomeObject myObject = new SomeObject();
myForm.formObject = myObject;
Run Code Online (Sandbox Code Playgroud)

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

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

如果你能提供一个简短而完整的程序,你的行为是你不理解的(理想情况下是一个控制台应用程序,只是为了让事情变得更简单和更简单),就可以更容易地用具体的术语来讨论这些事情.

  • 在单独的纸上的地址类比有助于掌握参考类型的概念. (3认同)

Dav*_*ita 7

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

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

希望能帮助到你 :)