Ref returns and ref locals in C# 7.0

C# 7.0 introduces ref returns and ref locals. Main goal of these new features is to make it easier for developers to pass around references to value types instead of copies of their values. This is important when working with large data structures that are implemented as value types. This blog post shows how to use ref returns and ref locals in Ć#.

Current ref and out arguments

We can use ref and out arguments to send some variable to method and let it modify the value of it. This way we can write methods that “return” more than one value. Ref lets value type in by reference. Out means that variable will get value in method where it is given as argument.


static int DoSomething(ref int i, out int i)
{
    // method code
}

C# 7.0 introduces support for ref returns and locals. This way we can move value type references between method calls instead of copies of values.

Ref return

Here is the example method that retruns first negative number from array or given return value when negative number is not found. To avoid copies of values it uses ref return.


static ref int FindFirstNegativeNumber(int[] numbers, ref int notFoundValue)
{
    for (var i=0; i<numbers.Length; i++)
    {
        if(numbers[i] < 0)
        {
            return ref numbers[i];
        }
    }

    return ref notFoundValue;
}

We don’t have to use ref keyword with numbers array because it is object and it is going to method by reference anyway. notFoundValue needs ref keyword because it is value type and without ref keyword we don’t have memory address to refer in allowed scope.

If we try to do something like this:


static ref int FindFirstNegativeNumber(int[] numbers, int notFoundValue)
{
    for (var i=0; i<numbers.Length; i++)
    {
        if(numbers[i] < 0)
        {
            return ref numbers[i];
        }
    }

    return ref notFoundValue;
}

To have reference we need ref or out keyword, Otherwise it is copy of value that lives in given method’s scope.

Ref locals

Methods that return reference to value are special because of how their return value is stored. We cannot assign ref return value to regular variable. We have to define variable as ref like shown in the following example;


static void Main(string[] args)
{
    var numbers = new[] { 1, 2, -4, 6, -8 };
    var returnValue = 0;

    ref var result = ref FindFirstNegativeNumber(numbers, ref returnValue);
result++;

    Console.WriteLine("Result: " + result);
    Console.WriteLine("\r\nPress any key to continue ...");
    Console.ReadKey();
}

Declaration of variable must use ref keyword. We cannot leave ref keyword out because otherwise it would be assignment of location to value and this is not allowed by compiler.

Wrapping up

Ref returns and locals seem like small addition to language but actually they help to write more performant code as there’s no need to move copies of values between methods. There are limitations to ref return value scopes but in most cases we don’t face situations where we cannot get rid of these limits.



See also

2 thoughts on “Ref returns and ref locals in C# 7.0

Leave a Reply

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