2016-03-30 2 views
1

В C#, если у меня есть объектная переменная в классе, а у второго класса есть объектная переменная, которая установлена ​​на один и тот же объект, как можно обновить обе переменные объекта, когда переменная объекта изменилась?Почему этот объект не обновляется?

Вот код, как пример:

public class Class1 
{ 
    public object obj { get; set; } 
} 

public class Class2 
{ 
    public object obj { get; set; } 
} 

private void SetObject() 
{ 
    var class1 = new Class1(); 
    class1.obj = "test"; 

    var class2 = new Class2(); 
    class2.obj = class1.obj; 

    class2.obj = "test2"; 
} 

В приведенном выше коде, при изменении class2.obj, то class1.obj остается неизменным. Как возможно для class1.obj иметь то же значение, что и class2.obj, если для любого значения установлено значение class2.obj?

+0

Вы пытаетесь установить на реальный объект вместо строкового объекта? – fbiazi

+0

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

+0

Это для учебных целей или для достижения определенной цели? Потому что короткий ответ - это не реально – Rob

ответ

0

Вы trowing значение из class2.obj прочь при выполнении

class2.obj = "test2"; 

Кроме того, вы можете изменить его, если class1.obj были объектом и вы измените свойство его либо на class1.obj или class2.obj. Не переназначение другого объекта.

3

Редактировать: Я добавил blog post, который, надеюсь, объясняет и демонстрирует более четко. Пожалуйста, не обижайтесь, потому что он говорит «для абсолютных новичков». Я не знаю, каков ваш опыт/опыт, но мне нравится писать с этой точки зрения.


class2.obj не является значением. Это ссылка на объект. Перед вызовом class2.obj = "test2", class2.obj содержит ссылку на строку «test».

Затем вы меняете его на ссылку на другой объект - строку «test2». class1.obj все еще указывает на тот же объект, который он сделал, который является другим объектом, строка «test».

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

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

Предположим, у нас есть этот класс:

public class ThingWithValue 
{ 
    public string Value { get; set; } 
} 

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

var thing1 = new ThingWithValue { Value = "A" }; 
var thing2 = new ThingWithValue { Value = "B" }; 

Это создает новую переменную, указывающую на тот же объект, thing1. Есть две переменные, но только один объект:

var thing3 = thing1; 

Так что, если я установить свойство на thing3 то я также установить его на thing1 потому что они оба тот же объект.

thing3.Value = "C"; 

Но если я это сделать:

thing1 = null; 

то единственное, что я меняю переменная - это уже не указывает на этот объект.Я не изменяю этот объект. Он все еще существует. thing3 не стал бы null. Он все еще указывает на тот же объект.

0

Здесь, в вашем случае, вы косвенно выполняете операцию со строкой, объект класса не отображается или не назначается. Следовательно, она подобна о следующем:

string s1 = "abc"; 
string s2 = s1; 
s2 = "123"; 
// this wont change the value of s1; 

Назначая строкового литерала к строковой переменной, Вы фактически создавать новый объект строки и назначен к существующему:

То, что вы на самом деле ожидается является что:

var class1Object1 = new Class1(); 
class1Object1.obj = "test"; 
var class1Object2 = new Class1(); 
class1Object2 = class1Object1; 
class1Object2.obj = "test2"; 

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

0

Он не будет обновлять другую переменную, потому что вы на самом деле изменяете указатель , а не объект.

Например, после запуска этого

class1.obj = "test"; 

Мы можем представить себе схему памяти следующим образом:

Mem Address Name  Value 
0x0001  Class1.obj 0x0003 
0x0002  Class2.obj 
0x0003  string  "test" 

Тогда мы управляем:

class2.obj = class1.obj; 

Так что теперь память выглядит :

Mem Address Name  Value 
0x0001  Class1.obj 0x0003 
0x0002  Class2.obj 0x0003 
0x0003  string  "test" 

И наконец:

class2.obj = "test2"; 

дает нам это:

Mem Address Name  Value 
0x0001  Class1.obj 0x0003 
0x0002  Class2.obj 0x0004 
0x0003  string  "test" 
0x0004  string  "test2" 

Обратите внимание, что значение Class1.obj «s не была изменена. Он все еще указывает на исходный объект.

+0

Как может указатель для Class1.obj указывает на новое значение класса2.obj всякий раз, когда Class2.obj изменяется? – user3736648

+0

@ user3736648 Короткий ответ - это невозможно в обычном C#. Долгий ответ: вам нужно «Class1» и «Class2» сохранить значение адреса памяти объекта (в данном случае «0x0003») вместо строки и вручную обработать разыменование. Если у вас нет фона в указателях и манипуляциях с памятью, и вы заинтересованы в этом, я бы посоветовал сначала использовать язык более низкого уровня, такой как C или C++. В противном случае существует определенно лучший способ сделать то, что вы пытаетесь достичь. Использование 'class1' mutable путем изменения' class2' - это рецепт катастрофы – Rob

0
class2.obj = class1.obj; 

Здесь вы присваиваете значение class1.obj классу2.obj, не изменяя его ссылку. Поэтому значение class1.obj не изменится при изменении значения class2.obj.

0

Это не будет работать, попробуйте использовать что-то вроде:

myclass a = new myclass(); 
a.integer = 1; 

myclass b = new myclass(); 
b.integer = 2; 

a = b; 
Смежные вопросы