.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!