2015-08-03 4 views
0

Я читал о типах ссылок и значениях в C#, но не знаю в следующем примере, почему y = 10, хотя x и y являются ссылочными типами?Конфликт в том, что объект является ссылочным типом

object x = 10; 
object y = x; 
x = 20; 
Console.WriteLine(y); //why y = 10 although x and y are reference types? 

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

+3

Ссылка и значение здесь не имеют значения. Вообще. Вы переназначили x. Это не повлияет на y в этом примере независимо от типа типа. –

+4

Используйте строку. Используйте int. Используйте свой собственный класс Foo. Они все ведут себя одинаково. –

+0

Что бы вы ожидали от вас? Зачем? –

ответ

0

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

class Complex 
{ 
    public int real; 
    public int imag; 
} 

static void Main(string[] args) 
{ 
    Complex c1 = new Complex(); 
    Complex c2 = new Complex(); 
    c2.real = 100; 
    c2.imag = 100; 

    object x = c1; 
    object y = x; 

    ((Complex)x).imag = 50; //y here is changed 

    x = c2; //y here isn't changed because this line makes x is now pointing on sth else which doesn't matter with the object referenced by y 

} 
+1

Там вы идете, это твердое понимание переназначения переменных * или * модификационных свойств объекта, на который ссылаются переменные. –

3

На данный момент мы игнорируем тип object. Когда вы делаете инициализации, как этот

SomeType y = x; 

y становится псевдонимом для x если SomeType является ссылочным типом class, или он становится копией из x если SomeType является типом значения struct.

Ситуация, когда становится видимой, является SomeType является mutable. В ситуациях со ссылочными типами изменение содержимого объекта, на которое ссылается x, также изменило бы y, потому что это тот же объект. Однако, если это копия, изменение x не влияет на y.

Поскольку ваш код использует объекты в штучной упаковке неизменен оберточный типа целочисленных примитивов, это назначение

x = 20; 

делает переменная x относится к совершенно другому неизменному объекту. Значение y остается неизменным.

+0

Да, идея заключается в неизменности типа ссылочного объекта. И присвоение означает, что ссылка ссылается на другое местоположение. Большое спасибо. – eman

+0

, но как int является неизменным, хотя я могу сделать: int i = 5; то i = 10; и это происходит в том же месте памяти? – eman

+0

@ user2036214 Класс оболочки объекта 'int'' System.Int32' является неизменным. 'int 'является примитивным, поэтому он определенно изменчив. Когда вы присваиваете целочисленную константу 'object', компилятор C# автоматически обертывает значение в объекте' System.Int32'. – dasblinkenlight

0

Заявление -

Object x = 10 

имеет специальное название и называется Бокс. Это завершает тип значения внутри ссылочного типа. Возможно, вы думаете, что это должно создать ссылку. Да ты прав. Но это также означает, что создается новый объект - как указано в документе doc -

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

https://msdn.microsoft.com/en-us/library/yz2be5wk.aspx

Теперь, когда вы делаете -

object y = x; 

Y и X имеют тот же объект здесь указывает на то же место памяти. Это хорошо. Но следующее заявление -

x = 20; 

вызывает исключение. Видите ли, это утверждение является еще одним боксом, и по мере того, как бокс создает новые экземпляры, это создает еще один новый объект со значением 20 и помещает/ссылается на него с помощью X.

Итак, Y указывает на последнюю ячейку памяти, где указывается X в новую ячейку памяти.

Вы можете понять, почему, посетив ссылку, упомянутую выше.

И если вы убедите меня в причине, как я могу изменить объект, на который ссылаются как x, так и y? => Вы не можете! Поскольку C# не поддерживает явные указатели, и вы используете типы значений.

Однако, если X и Y являются ссылочными типами (т. Е. Class объектов), вы могли бы это сделать.

3
object x = 10; 
object y = x; 

После этого x и y ссылкой на тот же объект:

x, y -> 10 

Но когда вы позволяете x = 20:

x -> 20 
y -> 10 

Вы можете обернуть значение с классом:

class Ref<T> 
{ 
    public T Value; 

    public static implicit operator T(Ref<T> x) 
    { 
     return x.Value; 
    } 

    public static implicit operator Ref<T>(T x) 
    { 
     return new Ref<T>() { Value = x }; 
    } 
} 

И потом:

Ref<int> x = 10; 
Ref<int> y = x; 

// x, y -> Ref -> 10 

x.Value = 20; 

// x, y -> Ref -> 20 

Console.WriteLine(y); // y is 20 (or rather y.Value is 20) 
Смежные вопросы