2010-12-03 2 views
44

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

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

ответ

32

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

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

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

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

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

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

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

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

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

4

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

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

Надеется, что это помогает :)

+0

Извините, что никпик здесь. Объекты не выводятся. Типы делают. Объект обычно является термином, используемым для описания экземпляра типа. – 2010-12-03 17:07:25

+0

Вы можете передать аргумент * по * ссылке, используя `ref`, но это не то же самое, что передать его * как * ссылку. Я думаю, что стоит отличать двух. – 2010-12-03 17:14:59

1

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

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

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

Смежные вопросы