in Development

Value and Reference types

This is a very very old topic and there is lot of information about it, so I’m not going to enter in detail about it.

Before to start, I’m just going to say that value types contain their data directly and reference types contain a reference to their data stored in a different place of the memory. In the case of .NET we know that value types are stored in the stack and reference types in the heap.

I think nowadays everybody has this concept clear, the whole idea behind this post comes because today I was reading some code and I so a “small” bug, probably due to a misunderstanding of what implies to pass reference types as parameters. Take a look to the next code.

   1: class ReferenceType
   2: {
   3:     public int Id;
   4: }
   6: class Program
   7: {
   8:     public static void Main()
   9:     {
  10:         ReferenceType t = new ReferenceType();
  12:         Console.Out.WriteLine(t.Id);
  14:         DoTest1(t);
  16:         Console.Out.WriteLine(t.Id);
  18:         DoTest2(ref t);
  20:         Console.Out.WriteLine(t.Id);
  22:         DoTest3(t);
  24:         Console.Out.WriteLine(t.Id);
  26:         Console.ReadKey();
  27:     }
  29:     public static void DoTest1(ReferenceType t)
  30:     {
  31:         t.Id = 1;
  32:     }
  34:     public static void DoTest2(ref ReferenceType t)
  35:     {
  36:         t.Id = 2;
  37:     }
  39:     public static void DoTest3(ReferenceType t)
  40:     {
  41:         t = new ReferenceType();
  42:         t.Id = 3;
  43:     }
  44: }

What do you think will be the output? Somebody could answer 0,1,2,3 but the output is 0,1,2,2.

But why is this?  The answer is quite easy, what we do in methods DoTest1 and DoTest3 is to pass a reference type by value; in the method DoTest2 we pass reference type by reference.

This means that methods DoTest1 and DoTest2, receive a reference to the value and consequently we can modify the value. But in method DoTest3 we are trying to modify the reference which is not possible because we passed it by value. So, to be able to modify the reference we need to pass it by reference and this is done adding the “ref” operator.

   1: public static void DoTest3(ref ReferenceType t)
   2: {
   3:     t = new ReferenceType();
   4:     t.Id = 3;
   5: }

After we do this change in method DoTest3 the output will be 0,1,2,3