How-To's

Ref local re-assignment – C# 7.3 in Rider and ReSharper

The Early Access Preview (EAP) versions of ReSharper 2018.2 and Rider 2018.2 come with support for C# 7.3. In this series, we are looking at these new language features in C# 7.3. Today, we let’s check out ref local re-assignment.

This post is part of a series:

Ref local re-assignment

In C#, it’s been possible for a while to work with references, using the ref keyword. For example, it’s possible to return a reference to a Person that is already in memory, rather than return a by-value version that will be copied.

public ref Person GetPerson(int id)
{
    // ...
}

If we’d call our method and assign the variable locally, this would essentially read the value of what was returned, and then assign it to a new variable:

var person = people.GetPerson(123);

Whenever we now make a change to the person, that change is made to the local copy of person, not to the one that was originally returned by GetPerson(). Even though that method returned a Person by reference.

C# 7.2 and C# 7.3 added a number of additions to working with references and the ref keyword. In C# 7.2, the ability to replace a referenced variable was added. Consider the following example:

void Example()
{
    var people = new[]
    {
        new Person { Name = "Person 1" },
        new Person { Name = "Person 2" }
    };

    ref var personRef = ref GetPerson(people, 0);

    // C# 7.2 - Assigning personRef to a new Person will *replace* the original element in our array
    personRef = new Person { Name = "Person X" };
    // people[0] will now be the new person we just assigned
}

public static ref Person GetPerson(Person[] people, int id)
{
    return ref people[id]; 
}

We have effectively re-assigned people[0] in this case, which may (or may not) be intentional. Use with caution!

Perhaps this was unintentional after all, and all we wanted to do was to re-use the personRef variable to hold a reference to another object. For those cases, C# 7.3 adds ref local re-assignment (spec), to make it possible to re-assign an existing reference:

void Example()
{
    var people = new[]
    {
        new Person { Name = "Person 1" },
        new Person { Name = "Person 2" }
    };

    ref var personRef = ref GetPerson(people, 0);

    // C# 7.3 ref re-assignment - note the 'ref' keyword in front of the assigned value
    // This will not change the value it points to, just update the reference itself.
    personRef = ref GetPerson(people, 1);

    // Now people[0] and people[1] are still the same. personRef holds a reference to people[1].
}

public static ref Person GetPerson(Person[] people, int id)
{
    return ref people[id]; 
}

Do keep in mind that, for example, changing personRef.Name will update the original person in our array as well.

Download ReSharper 2018.2 EAP now! Or give Rider 2018.2 EAP a try. We’d love to hear your feedback!

image description