In this article, we are still going to talk about methods but from a different perspective. We are going to learn how to pass our arguments by using the ref and out keywords.

For the complete navigation of this series check out: C# Back to Basics.

If you want to download the source code for our examples, you can do that from here Ref and Out Keywords Source Code.

This article is divided into several sections:

In the previous post, we were passing a value type arguments while calling our methods. Why is the type of argument important here?

Well, when we pass the argument of type int, double, decimal etc (basic value types), we do not pass the actual value but its copy. This means that our original values are not changed inside the methods, because we pass a new copy of the original value. As a result, all the operations inside a method are executed upon the copy value.

We can show this in an example:

class Program
{
    public static void ChangeAndWrite(int number)
    {
        number = 10;
        Console.WriteLine($"Inside ChangeAndWrite method, number value is: {number}");
    }
    static void Main(string[] args)
    {
        int number = 5;
        Console.WriteLine($"Value of the number prior to ChangeAndWrite call is: {number}");

        ChangeAndWrite(number);
        Console.WriteLine($"Value of the number after the ChangeAndWrite call is: {number}");

        Console.ReadKey();
    }
}

Value parameter - Ref and Out Keywords in C#

As we can see, the value of the number variable changes only inside the ChangeAndWrite method. But the original value is the same as before calling the ChangeAndWrite method. And again, this is because we are passing the exact copy of the original value.

Using Ref and Out Keywords

We can change this default behavior. If we want to change the original values inside our methods, we can do that by using ref and out keywords inside the method signature and inside the method call as well.

We can use the ref keyword only if the variable which we use as an argument is initialized before calling a method. By using the out keyword, we don’t have to initialize a variable before calling a method but, we must initialize it inside a method.

So, let’s simplify that. If we want to change an existing value of a variable inside a method, we are going to use the ref keyword. But, if we want to assign a completely new value to the variable inside a method, then we use the out keyword.

Example 1 for the Value Type

In the previous example, we saw how the value type variables behave if we don’t use the ref or out keywords. In this one, we are going to see the behavior of value type variables when we use those keywords:

class Program
{
    public static void ChangeRef(ref int numberRef)
    {
        numberRef = 25;
        Console.WriteLine($"Inside the ChangeRef method the numberRef is {numberRef}");
    }

    public static void ChangeOut( out int numberOut)
    {
        numberOut = 60;
        Console.WriteLine($"Inside the ChangeOut method the numberOut is {numberOut}");
    }
    static void Main(string[] args)
    {
        int numberRef = 15;
 
        Console.WriteLine($"Before calling the ChangeRef method the numberRef is {numberRef}");
        ChangeRef(ref numberRef);
        Console.WriteLine($"After calling the ChangeRef method the numberRef is {numberRef}");

        Console.WriteLine();

        int numberOut;
        Console.WriteLine("Before calling the ChangeOut method the numberOut is unassigned");
        ChangeOut(out numberOut);
        Console.WriteLine($"After calling the ChangeOut method the numberOut is {numberOut}");

        Console.ReadKey();
    }
}

Sending value parameter - Ref and Out Keywords in C#

This all is pretty clear. If we use the ref or the out keyword on the value type variable, its original value will change. But the difference is that with the out keyword we can use unassigned variables.

Example 2 for the Reference Type

We have learned, that the reference type doesn’t store its value inside its own memory location. It stores the address towards the memory location where the value is stored. Therefore when we send an argument as a reference type to the method and change that parameter, the original value is changed. This is because we are not sending the copy of the value but the copy of the address that points to the original value. This is the same thing as when we use the ref keyword with the value types.

Still, we can use the ref keyword with the reference types if we want to create a new object with the same address.

Let’s see all of this in an example:

class Program
{
    public static void ChangeColor(Pen pen)
    {
        pen.Color = Color.Green;
        Console.WriteLine($"Inside the ChangeColor method the color is {pen.Color}");
    }

    public static void CreateNewObjectWithoutRef(Pen pen)
    {
        pen = new Pen(Color.Red);
        Console.WriteLine($"Inside the CreateNewObjectWithoutRef method the color of new pen object is {pen.Color}");
    }

    public static void CreateNewObjectWithRef(ref Pen pen)
    {
        pen = new Pen(Color.Yellow);
        Console.WriteLine($"Inside the CreateNewObjectWithRef method the color of new pen object is {pen.Color}");
    }

    static void Main(string[] args)
    {
        Pen pen = new Pen(Color.Blue);

        Console.WriteLine($"Before ChangeColor method: {pen.Color}");
        ChangeColor(pen);
        Console.WriteLine($"After the ChangeColor method: {pen.Color}");

        Console.WriteLine();

        Console.WriteLine($"Before CreateNewObjectWithoutRef method: {pen.Color}");
        CreateNewObjectWithoutRef(pen);
        Console.WriteLine($"After CreateNewObjectWithoutRef method: {pen.Color}");

        Console.WriteLine();

        Console.WriteLine($"Before CreateNewObjectWithRef method: {pen.Color}");
        CreateNewObjectWithRef(ref pen);
        Console.WriteLine($"After CreateNewObjectWithRef method: {pen.Color}");

        Console.ReadKey();
    }
}

In the first method, we are not using the ref keyword. The value is changed because we pass the copy of the address in which the original value is stored. In the second method, the original value stays the same. That’s because we create a new object inside the method thus the new memory address is allocated. But in the third method, we are using the ref keyword and the original value changes. Why? Because with the ref keyword we are copying the same address to a new object.

Conclusion

Now we know how to use ref and out keywords with the value and reference types. This is quite a useful feature in C#, thus knowing how to work with those keywords is an advantage for the developers.

In the next post, we will talk about recursion and recursive methodsrecursion and recursive methods.