Important points regarding ref in C#
- ref keyword is used to return more than one values from a function.
- ref keywords need to be defined before you can pass them as a parameter to function
- Called method is not bound to assign any value to the ref parameter since it has already been initialized by calling method
Case Study
We need to find if a number i.e. 4 exist in an array and if exist we would like to change its value to 111
Example using C# 6.0
Consider below extension method which returns index of a number if it’s found in array
public static class NumberExtensions { public static int FindIndexOfNumber(this int[] numbers, int numberToSearch) { for (int i = 0; i < numbers.Length; i++) { if (numbers[i] == numberToSearch) { return i; } } throw new ArgumentException(string.Format("Number {0} not found", numberToSearch)); } }
And here is called method which finds 4 in array and change its value
style="display:block; text-align:center;"
data-ad-format="fluid"
data-ad-layout="in-article"
data-ad-client="ca-pub-5021110436373536"
data-ad-slot="9215486331">
int[] numbers = new[]{ 1, 2, 3, 4, 5, 6}; try { int index = numbers.FindIndexOfNumber(4); //Get Index of number so that we can change value later numbers[index] = 111;//change value at returned index } catch (Exception) { //Do nothing } Console.WriteLine("Value at index 3 is {0}", numbers[3]);//Output : Value at index 3 is 111
So as you can see that array is iterated twice, first time while searching the value i.e. inside FindIndexOfNumber method and second time while assigning value i.e.
numbers[index] = 111;
For small arrays, the performance impact is negligible but for very large arrays there will be a significant hit in performance and thus is not a good way of doing this.
Let’s try to create the same example in C# 7 using Locals as Ref feature
We will change our extension method as
public static class NumberExtensions { public static ref int FindReferenceOfNumber(this int[] numbers, int numberToSearch) { for (int i = 0; i < numbers.Length; i++) { if (numbers[i] == numberToSearch) { return ref numbers[i]; } } throw new ArgumentException(string.Format("Number {0} not found", numberToSearch)); } }
And our caller method will look like
style="display:block; text-align:center;"
data-ad-format="fluid"
data-ad-layout="in-article"
data-ad-client="ca-pub-5021110436373536"
data-ad-slot="9215486331">
private void btnReturnLocalAsRef_Click(object sender, EventArgs e) { int[] numbers = new[] { 1, 2, 3, 4, 5, 6 }; try { int index = numbers.FindReferenceOfNumber(4); //Get Index of number so that we can change value later index = 111;//No change in value since destination is not a ref type Console.WriteLine("Value at index 3 is {0}", numbers[3]);//Output: Value at index 3 is 4 //Correct Usage to store returning refs ref int refIndex =ref numbers.FindReferenceOfNumber(4); //Get Index of number so that we can change value later refIndex = 111; Console.WriteLine("Value at index 3 is {0}", numbers[3]);//Output: Value at index 3 is 111 } catch (Exception) { //Do nothing } }
A very handy feature that can save you lot of CPU while working with large arrays.
style="display:block; text-align:center;"
data-ad-format="fluid"
data-ad-layout="in-article"
data-ad-client="ca-pub-5021110436373536"
data-ad-slot="9215486331">
Some restrictions have been defined by language while returning ref locals
- You can only return refs that are “safe to return”: Ones that were passed to you, and ones that point into fields in objects.
- Ref locals are initialized to a certain storage location, and cannot be mutated to point to another.
All code samples are available at my GitHub profile
I am a corporate trainer and solution architect and have a great team of software professionals. Please contact in case you need our services by sending email to contact@techprocompsoft.com. Here is our company website .
Thanks for your very instructive illustrations of the new C# features.
Just wanted to point out a very minor copy-paste error in your example above. The comment is wrong in the line below, as this time refIndex IS a reference and the value in the array IS updated
refIndex = 111;//No change in value since destination is not a ref type
Regards,
Regis
Thanks for pointing out