eman
eman

Reputation: 195

Conflict in the fact that object is a ref type

I've read about ref and value types in c# but don't know in the following example why y = 10 although x and y are reference types?

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

And if you convince me of the reason, how could I change the object that is referenced by both x and y?

Upvotes: 0

Views: 111

Answers (4)

eman
eman

Reputation: 195

I got your answers and this example may make the thing clearer.

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

}

Upvotes: 0

Artem
Artem

Reputation: 1870

object x = 10;
object y = x;

After that x and y reference to same object:

x, y -> 10

But when you let x = 20:

x -> 20
y -> 10

You can wrap value with class:

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 };
    }
}

And then:

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)

Upvotes: 3

brainless coder
brainless coder

Reputation: 6430

The statement -

Object x = 10

has a special name and it is called Boxing. That is wrapping a value type inside a reference type. You might be thinking that this should create a reference. Yes you are right. But this also means a new object is created - as mentioned in the doc -

When a value type is boxed, a new object must be allocated and constructed.

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

Now when you do -

object y = x;

Y and X are same object here pointing to same memory location. This far is okay. But the next statement -

x = 20;

is causing the exception. You see, this statement is another boxing and as boxing creates new instances, this is creating another new object with value 20 and putting/referring that with X.

So, Y is pointing to the last memory location where X is pointing to a new memory location.

You can understand why by visiting the link I mentioned above.

And if you convince me of the reason, how could I change the object that is referenced by both x and y? => You can't! Because C# does not support explicit pointers and you are using value types.

However if X and Y were reference types (i.e. Class objects) then you could have done that.

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726987

Let's ignore the object type for a moment. When you make an initialization like that

SomeType y = x;

y becomes an alias to x if SomeType is a reference type class, or it becomes a copy of x if SomeType is a value type struct.

The situation when it becomes visible is when SomeType is mutable. In situations with reference types changing the content of the object referenced through x would also change y, because it's the same object. If it is a copy, however, changing x has no effect on the y.

Since your code uses objects of boxed immutable type wrapping integer primitives, this assignment

x = 20;

makes variable x refer to an entirely different immutable object. The value of y remains unchanged.

Upvotes: 3

Related Questions