Когда копируется значение/объект 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 и т. д., Похоже, всегда копируются, за исключением случая метода clone выше.

мой вопрос в том, не принимая во внимание использование ref ключевое слово в функциях, когда объект копируется и когда объект ссылается в каждом случае вопроса (т. е. при переходе к функциям, при установке в качестве других объектов (например, первые два примера выше), при копировании переменных-членов, таких как третий пример и т. д.)?

3 ответов


трудно ответить на такой вопрос точно, не тратя ужасно много времени, тщательно выбирая слова.

Я сделал это в нескольких статьях, которые вы можете найти полезными:

это не значит, что статьи идеальны, конечно-далеко от этого - но я пытался быть как как можно яснее.

Я думаю, что одна важная вещь-разделить две концепции (передача параметров и ссылка на типы значений) в вашей голове.

смотреть на ваши конкретные примеры:

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

это означает, что myForm.formObject и myObject обратитесь к тому же экземпляру SomeObject - как два человека, имеющие отдельные листы бумаги, на каждом из которых написан один и тот же адрес. Если пойти по адресу на одном листе бумаги и покрасить дом в красный цвет, то перейти по адресу на втором листе бумаги, вы увидите красный дом.

неясно, что вы подразумеваете под "а затем измените объект в форме", потому что тип, который вы предоставили, является неизменяемым. Изменить сам объект невозможно. Вы можете изменить myForm.formObject для ссылки на другой экземпляр SomeObject, но это все равно, что нацарапать адрес на одном листе бумаги и написать на нем другой адрес. Это не изменит того, что написано на другой части бумага.

если бы вы могли предоставить короткий, но полное программа, поведение которой вы не понимаете (в идеале консольное приложение, просто чтобы держать вещи короче и проще), было бы проще говорить о вещах в конкретных терминах.


Привет, Миша Все объекты, производные от ValueType, такие как struct или другие примитивные типы, являются типами значений. Это означает, что они копируются всякий раз, когда вы назначаете их переменной или передаете их как параметр метода. Другие типы являются ссылочными типами, это означает, что при назначении ссылочного типа переменной не ее значение, а адрес в пространстве памяти присваивается переменной. Также следует отметить, что вы можете передать тип значения в качестве эталона, используя ключевое слово ref. Вот синтаксис

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

надеюсь, что это помогает :)


Что касается клонирования ваших объектов, если значения, которые вы копируете из одного объекта в другой, являются ссылочными типами, то любое изменение этих значений в исходном объекте повлияет на значения в скопированном объекте (поскольку они являются просто ссылками на тот же объект)

Если вам нужно клонировать объект, который имеет свойства, которые являются ссылочными типами, вам нужно либо сделать эти типы клонируемыми, либо сделать их ручную копию, создав новые экземпляры как требуемый.

Conside с помощью IClonable интерфейс, хотя это не лучшее из решений имхо.