C# 7 Features — Ref Return and Ref Local

Sena Kılıçarslan
C# Programming
Published in
6 min readMar 18, 2019

In this post, I will write about ref return and ref local which are supported in C# starting with C# 7.0.

For a better understanding of this post, I suggest you read the below post where I explained Value / Reference Type, Stack and Heap.

A reference return value allows a method to return a reference (alias) to a variable back to a caller. The caller can then choose to treat the returned variable as if it were returned by value or by reference.

Similar to ref values passed as method arguments, ref returns can be modified by the caller, and any changes (assignments) to the value will reflect to the original value returned from the method.

The caller can create a new variable that is itself a reference to the returned value, called a ref local.

Below is a method with ref return:

To get a reference of a ref return value, you will need to use ref locals and also put the ref keyword in front of the method (ref in both left and right).

You can also call this method without the ref keyword, making the value returned by value.

The return value must have a lifetime that extends beyond the execution of the method. In other words, it cannot be a local variable in the method that returns it. It can be an instance or static field of a class, or it can be an argument passed to the method.

As you see in the following examples, trying to return a local variable (value type or reference type) gives compile error.

Value type local variable example
Reference type local variable example

However, array elements can be returned by reference even if the array type variable is a local variable:

Array as local variable

The reason is “Arrays are classes. They are allocated on the GC heap so the reference stays valid beyond the method call.“. For further information on this issue, you can refer to this Stackoverflow post.

Now, let’s do some examples and understand the subject better.

In the first example, we will use a class which has a field of an array with int (value type) elements.

Output:

As you see, value of the first element only changes after the below call where we use ref local variable:

Changing the value of the variable returned by the other two method calls below has no effect on the original array element:

In the second example, we will use a class which has a field of an array with Student type (reference type) elements.

Output:

Now, let’s go step by step and understand what happened.

At the beginning (before any function call) the first student in the classroom is Alice.

First, we get the name of the first student (by value)

and then change it to Sarah:

Now, if we check the first student in the classroom we find that Alice’s name changed to Sarah. We haven’t used ref return and ref local yet and in the above case where the array elements were integers, the first number did not change in this case. The reason is here we use a Student class which is a reference type as array element. As written in the aforementioned post,

If you assign a reference type variable to another, as reference type variables represent the address of the variable, the reference is copied and both variables point to the same location of the heap.

Next, we get the first student in the classroom by reference and assign it to a ref local:

We see that the first student in the class is still Sarah. Then we change this variable to Cate.

After checking the classroom we see that Sarah’s name changed to Cate permanently.

At this point, I want to point out the difference between these two types of calls although they produced the same effect. If you noticed, I inserted a line before the first method call:

After nulling this value, we could still access the first student through the call.

However, after the below line we could not access the first student:

and got the following error:

The reason is firstStudentByReference is an alias for the first student returned from the method and any changes to this variable directly reflects to the original value.

I did a similar example in order to explain the difference between Passing by Value and Passing By Reference a reference type variable in the Passing Parameters in C# post. If you are interested, you can check that.

Lastly, I want to mention some restrictions that apply to ref return:

  • The return value cannot be the literal null. But it can be an alias to a variable whose value is currently the null value or a nullable type for a value type.
  • The return value cannot be a constant, an enumeration member, the by-value return value from a property, or a method of a class or struct.
  • Methods returning by reference can’t have the return type void.
  • Reference return values are not allowed on async methods. An asynchronous method may return before it has finished execution, while its return value is still unknown.

I hope you found this post helpful and easy to understand. Please let me know if you have any questions and/or corrections.

Bye C#ers :)

References

https://docs.microsoft.com/tr-tr/dotnet/csharp/programming-guide/classes-and-structs/ref-returns

https://blogs.msdn.microsoft.com/mazhou/2017/12/12/c-7-series-part-7-ref-returns/

--

--

Sena Kılıçarslan
C# Programming

A software developer who loves learning new things and sharing these..