0

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?

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
eman
  • 195
  • 1
  • 1
  • 8

4 Answers4

3

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.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • yes, the idea is in the immutability of the type of the referenced object. And assigning is making the reference refers to another location. Thanks a lot. – eman Aug 03 '15 at 01:09
  • but how int is immutable although I can make: int i = 5; then i = 10; and this happens in the same memory location? – eman Aug 03 '15 at 01:12
  • @user2036214 `int`'s object wrapper class `System.Int32` is immutable. `int` is a primitive, so it's definitely mutable. When you assign an integer constant to `object`, C# compiler automatically wraps the value in a `System.Int32` object. – Sergey Kalinichenko Aug 03 '15 at 01:13
  • @user2036214, immutability, mutability, structs, classes, none of that has any relevance here, to be honest. This is simple reassignment, and it behaves the same for any type that x happens to be. Those terms are useful to understand *in general*, but the point of your x and y here is much simpler. It's just reassignment, no need to get lost in the weeds with the other terms being bandied about. – Anthony Pegram Aug 03 '15 at 01:15
3
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)
Artem
  • 1,773
  • 12
  • 30
0

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.

brainless coder
  • 6,310
  • 1
  • 20
  • 36
0

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

}
eman
  • 195
  • 1
  • 1
  • 8
  • 1
    There you go, that's a solid understanding of reassignment of a variable *versus* modifying properties of an object referenced by variables. – Anthony Pegram Aug 03 '15 at 01:42