Подтвердить что ты не робот

Когда значение С#/объект копируется и когда копируется его ссылка?

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

Например, если я отправляю объект в другую форму, то есть:

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 в функциях, когда объект копируется и когда объект получает ссылку в каждом случае вопроса (т.е. при переходе к функциям при настройке как и другие объекты (например, первые два приведенных выше примера), при копировании переменных-членов, таких как третий пример и т.д.)?

4b9b3361

Ответ 1

Трудно ответить на этот вопрос точно, не затрачивая много времени на тщательное изложение ваших слов.

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

Это не значит, что статьи идеальны, конечно - далеко от них, но я старался быть настолько ясным, насколько могу.

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

Чтобы посмотреть на конкретные примеры:

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

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

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

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

Ответ 2

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

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

Надеюсь, это поможет:)

Ответ 3

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

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

Conside, используя IClonable, хотя он не лучший из решений imho.