.NET Tools
Essential productivity kit for .NET and game developers
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:
- Declaration expressions in initializers and queries
- Tuple equality
- Unmanaged, delegate and enum type constraints
- Ref local re-assignment
- Fixed pattern and simplified access to fixed size buffer elements
- C# updates for stackalloc
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!
