In an earlier post, we discussed the readability factor of the reference semantics, mentioning how it kind of makes the code less readable. However, that doesn’t take away the big door of opportunities the new features add. Consider the following scenario.
As a developer, you want to develop a extension method called Increment for Type "int", which increments the value by 1. The extension method should have a void return type. We would ideally would like to do the following. int testValue = 1; testValue.Increment(); Console.WriteLine(testValue); // This should print a value 2;
Now, prior to C# 7, this was difficult. There was no way we could pass a reference of a value type to an extension method. Which means that every time we call the extension method, we would be passing a copy of the value, rather than the reference, increment the copied value and then just throw away the value. The above code would print a value “1”.
public static int Increment(this ref int Val) => ++Val;
public static ref int Increment(this ref int data) { ++data; return ref data; } int testValue = 1; ref int pointsToTestValue = ref testValue.Increment(); Console.WriteLine(testValue); pointsToTestValue++; Console.WriteLine(testValue);
The Increment method increments the value as it did earlier. Furthermore it now returns the same value as reference. Do note the changes in syntax for invoking as well as defining a method that return ref.
The output of above code would be
2 3
There might be scenarios where you might have to pass a data as reference, but ensure it doesn’t change. Here is where the new ‘in’ parameter comes in. The “in” keywords accepts the data by reference, but ensure that a developer who works on in future doesn’t change the value accidentally. “in” can be used in interface as well, to ensure that the implementing classes doesn’t change the value in the method.
public int Increment(in int data) { ++data; // this is not allowed return data; }
static public ref readonly int Increment(ref int data) => ref data; ref readonly int readonlyReference = ref Increment(ref h); readonlyReference++; // This is not allowed.
One obvious question of having a reference return type would be , what happens to the scope ? Does that mean GC needs to be aware of references outside scope of a method ? Not exactly, the Language team has thought well about it and has implemented certain safety constrains. The method can only return a ref that either came as a parameter or are in same heap. You cannot return a reference that is created within the method.
We will cover some more features of C# 7.x in coming posts, especially the ones that has to do with reference semantics.