Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Ref Returns and Ref Locals in C# 7.0

DZone's Guide to

Ref Returns and Ref Locals in C# 7.0

C# 7.0 sees the introduction of ref returns and ref locals. If you're at all curious as to what they are and what purpose they serve, then this article is for you.

· Web Dev Zone ·
Free Resource

Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.

C# 7.0 introduces ref returns and ref locals. The 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 C#.

Current Ref and Out Arguments

We can use ref and out arguments to send some variables to the method and let it modify the value of this method. This way we can write methods that “return” more than one value. Ref lets the value type in by reference. Out means that the variable will get a value in the method where it is given as an 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 returns the first negative number from an array or gives a return value when a 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 the ref keyword with a numbers array because it is an object and it is going to the method by reference anyway. notFoundValue needs the ref keyword because it is a value type and without the ref keyword we don’t have a memory address to refer to in the 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 a reference, we need the ref or out keyword. Otherwise, it is a copy of the value that lives in the given method’s scope.

Ref Locals

Methods that return a reference to a value are special because of how their return value is stored. We cannot assign a ref return value to a regular variable. We have to define a variable as ref as 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();
}

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

Wrapping Up

Ref returns and locals seem like a small addition to the 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.

Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.

Topics:
c# ,web dev ,c# 7.0 ,c# keywords

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}