Sunday 28 September 2014

The difference when passing a reference type by or without the Ref keyword C#

Assumption : Reference type are always passed by reference in C#. 
Nota : the assumption becomes false if object is a value type ( int, float , struct ... so immutable ), and the difference is trivial.

Let's consider the following methods :

void Fill2(ref Object1 input)
void Fill3(Object1 input)

At a first glance, there is no difference between the 2 signatures because in the two cases, the parameter is passed by reference ( assumption). At the exit of those functions, the object should have some of its properties updated.


The main difference by using the Ref keyword actually stands in the method implementation as we will see in the example ( the source code is at the end of this post ).
In a few words :
- Ref guarantees that method will work on the same reference inside the method. So if the method handles a check if null against the object and creates a new instance if object is null , then sets some properties, Ref keyword ensures that the same reference is used during this process and the last updated values are available after the method call. If Ref keyword is not provided and the method creates a new instance, the reference is lost and the object remains as it was being before the method call.

Concrete example : Fill3 and Fill4 methods are the most relevant study case.

namespace Devenva.Demo.Solution.RefKeyword
{
       class Program
      {
        static void Main(string[] args)
        {
            {
               Object1 obj = new Object1() { Name = "Bob" };
               Console.WriteLine("Name before = " + obj.Name);
               Fill1(obj);
               Console.WriteLine("Name after = " + obj.Name);
            }

            {
              Object1 obj = new Object1() { Name = "Bob" };
              Console.WriteLine("Name before = " + obj.Name);
              Fill2(ref obj);
              Console.WriteLine("Name after = " + obj.Name);
            }

            {
             Object1 obj = null;
             Fill3(obj);
             Console.WriteLine(obj.Name);
            }

           {
              Object1 obj = null;
              Fill4(ref obj);
              Console.WriteLine(obj.Name);
           }

           Console.WriteLine("End");
          Console.ReadLine();
    }

         static public void Fill1(Object1 input)
        {
            Console.WriteLine("*** Apply Fill1 method ***");
            input.Name = "Peter";
        }
        static public void Fill2(ref Object1 input)
        {
            Console.WriteLine("*** Apply Fill2 method ***");
            input.Name = "Kely";
        }
        static public void Fill3(Object1 input)
        {
            Console.WriteLine("*** Apply Fill3 method ***");
            if (input == null) {
               input = new Object1();
            }
           input.Name = "Dylan";
        }
        static public void Fill4(ref Object1 input)
        {
            Console.WriteLine("*** Apply Fill4 method ***");
           if (input == null)
           {
              input = new Object1();
           }
            input.Name = "Greg";
        }
   }
   public class Object1
  {
    public string Name { get; set; }
  }

}
In the following example, an exception is thrown after the call of method Fill3 ( it's normal - refer to my previous commentary)

No comments:

Post a Comment