Why can I ref return an item of an array that only exists inside the method?

I was trying out the new ref returns of C#7.

I am able to compile and build this:

        public ref string MisUseRefReturn(int index)
    {
        string[] array = { "a", "b", "c", "d" };
        return ref array[index]; //array[2] gets out of scope when this method returns!
    }

According to MSDN: The return value cannot be a local variable in the method that returns it; it must have a scope that is outside 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. Attempting to return a local variable generates compiler error CS8168, "Cannot return local 'obj' by reference because it is not a ref local."

So why does this compile? When I execute this method, the returned reference shows the correct string.

Jon Skeet
people
quotationmark

Think of the array element as if it were an instance field of the array. Imagine your array were:

public class FourElementStringArray
{
    public string element0;
    public string element1;
    public string element2;
    public string element3;
}

Then your code is equivalent to:

public ref string MisUseRefReturn(int index)
{
    var array = new FourElementStringArray
    {
        element0 = "a",
        element1 = "b",
        element2 = "c",
        element3 = "d"
    };
    // TODO: do this dynamically based on index
    return ref array.element2;
}

That abides by the piece of documentation you quoted:

It can be an instance or static field of a class, or it can be an argument passed to the method.

Is this useful? Not particularly. Is it dangerous? No.

The latter part is the important point. Using the regular array, if the caller assigns a new value, that's fine - it's replacing an element of an array, on the heap. The array can't be garbage collected while the array element reference exists; all is basically okay.

What the compiler rule is trying to prevent is the use of a returned reference to somewhere on the stack which has then been popped by the method returning. The array itself isn't on the stack, so there's no problem here.

people

See more on this question at Stackoverflow