Will Swap Work If C# Manipulates Objects By Reference?

Introduction

"If C# manipulates objects by reference, will a swap work?" - This issue must certainly have troubled quite a lot of beginners. C# does manipulate objects by reference, and all object variables are references. On the other hand, C# does not pass method arguments by reference; it passes them by value (even if the method arguments are of reference type). Thus, a regular swap method will not work!

Let's come from the beginning, we know that there are four kinds of formal parameters in a C# method declaration, namely

  • Value parameters, which are declared without any modifiers. (default)
  • Reference parameters are declared with the ref modifier.
  • Output parameters, which are declared with the out modifier.
  • Parameter arrays, which are declared with the params modifier.

Thus if there is no method parameter keyword (ref or out), the parameter can have a value associated with it. That value can be changed in the method, but that value will not be reflected when the control passes back to the calling procedure. This is true for all value types. Now, consider a reference type, an object. If we pass an object to a method and if the value of its member is changed, it will be retained even when the control is passed back to the calling procedure! This is because objects are manipulated by reference.

If so, then if we pass two objects to a regular swap method and come back to the calling procedure to see whether they have been swapped, they would have not! Look down the code below,

using System;
namespace SwapExample
{
    class Class1
    {
        public int x;
        public int y;

        public Class1(int xval, int yval)
        {
            x = xval;
            y = yval;
        }
    }
    class SwapTest
    {
        private static void SwapRef(ref Class1 param1, ref Class1 param2)
        {
            Class1 temp = param1;
            param1 = param2;
            param2 = temp;
        }
        private static void BadSwapNoRef(Class1 param1, Class1 param2)
        {
            param1.x = 100;
            param1.y = 200;
            Class1 temp = param1;
            param1 = param2;
            param2 = temp;
        }
        public static void Main(string[] args)
        {
            // Instantiating
            Class1 obj1 = new Class1(0, 0);
            Class1 obj2 = new Class1(0, 0);
            // Initial values of the instances obj1 and obj2
            Console.WriteLine("Initial values:");
            Console.WriteLine("X: " + obj1.x + " Y: " + obj1.y);
            Console.WriteLine("X: " + obj2.x + " Y: " + obj2.y);
            Console.WriteLine();
            // Calling BadSwapNoRef
            BadSwapNoRef(obj1, obj2);
            Console.WriteLine("After BadSwapNoRef:");
            Console.WriteLine("X: " + obj1.x + " Y: " + obj1.y);
            Console.WriteLine("X: " + obj2.x + " Y: " + obj2.y);
            Console.WriteLine();
            // Calling SwapRef
            Console.WriteLine("After SwapRef:");
            SwapRef(ref obj1, ref obj2);
            Console.WriteLine("X: " + obj1.x + " Y: " + obj1.y);
            Console.WriteLine("X: " + obj2.x + " Y: " + obj2.y);
            Console.WriteLine();
        }
    }
}

 The output of the above program is as follows.

outputswap.cs

Fig 1. Output of swap.cs

In the above program, we pass the instances obj1 and obj2 of class1 to the badswap_noref() method and see that they are not actually getting swapped. This is what actually happens in the badswap_noref method. Not the actual references obj1 and obj2 are passed. But a copy of the references is passed. So param1 and param2 contain a copy of the actual references obj1 and obj2, respectively. We are able to modify the values of X and Y in the badswap_noref method through param1 and param2 because param1 and param2 still point to the same address locations referred to by obj1 and obj2. But what we are swapping is only param1 and param2, the method references, which are not retained when we come back to the calling procedure, Main().

Fig 2. Object reference and method reference

Fig 3. Before and after badswap_noref

Thus, in C#, a swap method can be made possible by using the ref keyword. In such a case, we pass the object references explicitly by reference and not by value, thus being able to swap them right in the called method.

Fig 4. Before and after swap_ref


Similar Articles