Ref Returns and Ref Locals in C#

Ref Returns and Ref Locals in C#

In this article, I am going to discuss how to use Ref Returns and Ref Locals in C# with examples. These two new features are introduced as part of C# 7. Please read our previous article before proceeding to this article where we discussed how to work with the Local Functions in C# with examples. As of now, we have used ref as the method parameter. But from C# 7, now we can use ref keyword as the return type of method as well as we can also create local variables using the ref keyword. Before understanding these two new features (Ref Returns and Ref Locals in C#) let’s have a look at how we can pass the data and reference as of now.

  1. Passing by Value
  2. Passing by Reference
  3. Out parameter

Let’s discuss these concepts first by taking some simple example before understanding the ref returns and ref locals in c#.

Passing by Value in C#

If we declare a parameter of a value type, then the value is allocated within the scope of the method and destroyed immediately at the end of the method execution. Thus, the changes to the value will not affect the caller of the method.

Let’s understand Pass by Value in C# with an example.

In the following example, the method PassByValue(int x) receives a copy of a value type. The variable “x” is allocated within the method. While invoking this method we passed a copy of the variable “no” not the actual variable. So the change to “x” only happens within the scope of the PassByValue() method which will not affect to the caller of the method.

class Program
{
    static void Main(string[] args)
    {
        int no = 1;
        PassByValue(no);
        Console.WriteLine($"After the invocation of {nameof(PassByValue)} method, {nameof(no)} = {no}");

        Console.WriteLine("Press any key to Exit.");
        Console.ReadLine();
    }

    static void PassByValue(int x)
    {
        x = 2;
    }
}

When we run the application, it will give us the following output.

Ref Locals and Ref Returns in C#

As you can see in the above image, it will print the value as 1 because a copy of the value is passed, the value of “no” never changes and thus after the invocation of the PassByValue() method, the variable no remains unchanged.

Passing by Reference in C#

If you want to return the changed data from a method, then you need to use a return type for that method. But in C#, there are some other ways to return values from a method. One of the ways is to declare a parameter with the ref modifier. This allows for returning not only one value but multiple values from a method in C#. With the ref parameters in C#, the method can receive and return a value.

Let us understand Pass by value in C# with an example.

In the following example, the parameter x of the PassByReference() method has been assigned with the ref modifier. This “ref” modifier in C# indicates that the method invocation is going to happen by using a pointer. The variable x references the allocated value of the variable “no“. Thus changing the value to 2, the variable “no” now contains the changed value after the invocation of PassByReference() method.

class Program
{
    static void Main(string[] args)
    {
        int no = 1;
        PassByReference(ref no);
        Console.WriteLine($"After the invocation of {nameof(PassByReference)} method, {nameof(no)} = {no}");

        Console.WriteLine("Press any key to Exit.");
        Console.ReadLine();
    }

    static void PassByReference(ref int x)
    {
        x = 2;
    }
}

Output:

Ref Locals and Ref Returns in C#

With the change, the result on the output console is after the invocation of PassByReference, no = 2.

Out Variable in C#:

As we already discussed with the help of ref modifier in C#, a value can be passed to a method and also the value can be returned from the method. But, if we have a scenario where we need to only return the value from the method, then in such scenarios we need to use the out modifier in C#.

Let us understand out variable in C# an example.

In the following example, in order to call the OUT method, the variable no that is passed as a parameter to the OUT method does not need to be initialized. It is initialized within the method OUT.

class Program
{
    static void Main(string[] args)
    {
        int no;
        OUT(out no);
        Console.WriteLine($"After the invocation of {nameof(OUT)} method, {nameof(no)} = {no}");

        Console.WriteLine("Press any key to Exit.");
        Console.ReadLine();
    }

    static void OUT(out int x)
    {
        x = 2;
    }
}

Output:

Ref Locals and Ref Returns in C#

When we run the application, the value returned from the OUT method is shown, after the invocation of OUT method, no = 2. With C# 7.0, it offers a shorter syntax for invoking the method without parameters. The variable can be declared directly within the invocation.

Let understand this with an example.
class Program
{
    static void Main(string[] args)
    {
        OUT(out int no);
        Console.WriteLine($"After the invocation of {nameof(OUT)} method, {nameof(no)} = {no}");

        Console.WriteLine("Press any key to Exit.");
        Console.ReadLine();
    }

    static void OUT(out int x)
    {
        x = 2;
    }
}

OUTPUT:

Ref Locals and Ref Returns in C#

The point that you need to keep in mind is if a method just returns one value, then it’s always better to use a return type instead of the out modifier. OK. That’s cool. Let’s move to our main topic that is Ref local and Ref return in C# which was introduced as part of C# 7.

Ref Local in C#

The Ref local in C# is a new variable type which is used to store the references. It is mostly used in conjunction with Ref returns to store the reference in a local variable. That means Local variables now can also be declared with the ref modifier.

Let us understand Ref local in C# with one example.

In the following example, the variable no2 references variable no1, and thus changing no2 changes no 1 as well:

class Program
{
    static void Main(string[] args)
    {
        int no1 = 1;
        ref int no2 = ref no1;
        no2 = 2;
        Console.WriteLine($"local variable {nameof(no1)} after the change: {no1}");

        Console.WriteLine("Press any key to Exit.");
        Console.ReadLine();
    }
}

Output:

Ref Locals and Ref Returns in C#

Ref Returns in C#

As a developer, you may be aware of the C# “ref” keyword and its behaviors. As we know the ref keyword returns the address of the variable rather than the value. It can also be used with the reference type where new memory allocation has to be done within the calling method.

Before C# 7.0, the ref was only used to be passed as a parameter in a method, however, there was no provision to return it and use it later. With C# 7.0, this constraint has been waived off and now you can return references from a method as well. This change is really adding flexibility to handle the scenarios when we want references to return in order to make an in-lined replacement.

Let us understand Ref Returns in C# with an example.

In the following example, I am searching for an odd number inside an integer array and if it is not found throwing an exception, the method is not returning it as value but as a reference. So, we need to store that value which has been returned as a reference. To store it in a local variable, we can use ‘ref’ keyword with local variables, known as ref locals in C#.

class Program
{
    public ref int GetFirstOddNumber(int[] numbers)
    {
        for (int i = 0; i < numbers.Length; i++)
        {
            if (numbers[i] % 2 == 1)
            {
                return ref numbers[i]; //returning as reference  
            }
        }
        throw new Exception("odd number not found");
    }

    static void Main(string[] args)
    {
        Program p = new Program();
        int[] x = { 2, 4, 62, 54, 33, 55, 66, 71, 92 };

        ref int oddNum = ref p.GetFirstOddNumber(x); //storing as reference  
        Console.WriteLine($"\t\t{oddNum}");
        oddNum = 35;

        for (int i = 0; i < x.Length; i++)
        {
            Console.Write($"{x[i]}\t");
        }

        Console.WriteLine();
        Console.WriteLine("Press any key to exist.");
        Console.ReadKey();
    }
}

If you print “oddNum” first time, then it will print 33 but after that, I have re-assigned its value and set “oddNum =35” now iterating the array and printing elements of array and you can see that whatever I have done, modification for “oddNum” from outside is also reflecting inside the array and internal value has been modified from 33 to 35.

Output:

Ref Returns and Ref Locals in C#

In the next article, I am going to discuss the Generalized async return types in C# with some examples.

SUMMARY

In this article, I try to explain how to use Ref Returns and Ref Locals in C# step by step with some simple examples. I hope this article will help you with your need. I would like to have your feedback. Please post your feedback, question, or comments about this article.

Leave a Reply

Your email address will not be published. Required fields are marked *