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 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 the 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 examples 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.

Example: Pass by Value in C# 

Let us understand Pass by Value in C# with an example. Please have a look at the below example. In the below 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 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.

Example: Pass by Reference in C#

Let us understand Pass by Reference in C# with an example. Please have a look at the below example. In the below 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 the 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. The point that you need to remember is in the case of ref, the variable must be initialized before sending to the calling method.

Out Variable in C#:

As we already discussed with the help of the 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#.

Example: Out Variable in C#

Let us understand Out Parameter in C# with an example. Please have a look at the below example. In the below 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 Out Method. Here, initialization is optional, as it is mandatory to be initialized in the Out Method body, else you will get a compile-time error.

class Program
{
    static void Main(string[] args)
    {
        int no;
        OUT(out no);
        Console.WriteLine($"After the invocation of OUT method, 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 OutMethod is shown, after the invocation of the OutMethod, 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.

Example: Out Variable Declare within Method call in C#

Let us understand How to Declare Out Parameter within Method call in C# with an example. Please have a look at the below example. Here, we are declaring the out variable number directly at the time of the method call.

class Program
{
    static void Main(string[] args)
    {
        OUT(out int no);
        Console.WriteLine($"After the invocation of OUT, 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#

Difference between Ref and Out Parameters in C#

Ref:
  1. The parameter or argument must be initialized first before it is being passed to ref.
  2. It is not required to assign or initialize the value of a parameter (which is passed by ref) before returning to the calling method.
  3. Passing a parameter value by Ref is useful when the called method is also needed to modify the passed parameter.
  4. It is not compulsory to initialize a parameter value before using it in a calling method.
  5. The ref tells the compiler that the object is initialized before entering the function. so the data can be passed bi-directionally.
  6. When you want to pass the value as well as you want to return the modified value then you need to use ref.
Out:
  1. It is not compulsory to initialize a parameter or argument before it is passed to an out.
  2. A called method is required to assign or initialize a value of a parameter (which is passed to an out) before returning to the calling method.
  3. Declaring a parameter to an out method is useful when multiple values need to be returned from a function or method.
  4. A parameter value must be initialized within the calling method before its use.
  5. The out tells the compiler that the object will be initialized inside the function, so the data is passed only in a unidirectional way i.e. from the called method to the caller method.
  6. When you only want to return the value from the method then you need to use the out parameter.

Note: 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 or ref 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 that 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. If this is not clear at the moment, then don’t worry, we will try to understand with some examples.

Example: Ref local in C#

Let us understand Ref local in C# with an example. Please have a look at the below example. In the below example, first, we create an integer variable called no1 and initialized it with the value 1. Then we create another integer variable with the ref keyword with the name no2 and initialized it with the reference of no1 i.e. ref int no2 = ref no1; Now, the variable no2 references variable no1, and thus changing no2 changes no1 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. 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. If this is not clear at the moment, then don’t worry we will try to understand this concept with some examples.

Example: Ref Returns in C#

Let us understand Ref Returns in C# with an example. Please have a look at the below example. In the below 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 the value but as a reference. So, we need to store that value that has been returned as a reference. To store it in a local variable, we can use the ‘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” the 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 the array and you can see that whatever I have done, a 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 examples. Here, 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 *