Ref and Out improvements in C# 7.0

If you have been observing last few releases of C#, the key focus of C# language team is to improve the developer productivity by reducing the repetitive/common code and performance of the application. First one, helps a lot in writing cleaner and concise code so it mainly contains logic instead of number of lines for null check etc.

ref and out keywords are available with C# since long and very useful in many scenarios. These were serving the purpose quite beautifully but there were few improvements in C# 7.0 which makes it more attractive. In this post, I am not going to discuss the basics of these keywords detail but mainly focus on the improvements in C# 7.0.

Ref keyword – This keyword is used to pass the parameter by reference (even if it is value type) to a method. When we pass the parameter by reference, any change that takes place in the called method also reflects in calling method. ref keyword should be used by in calling method while passing the parameter and in the called method as well. Also unassigned variable cannot be passed as well. Lets see a quick example

static void Main(string[] args)
{
    Point p;
    p.x = 10;
    p.y = 20;

    UpdateCoordinates(ref p);

    Console.WriteLine($"Point coordinates x : {p.x}, y : {p.y}"); // Output: Point coordinates x : 20, y : 40

    Console.ReadKey();
}

static void UpdateCoordinates(ref Point p)
{
    p.x = 20;
    p.y = 40;
}

public struct Point
{
    public int x, y;
}

Here Point is a value type and it is passed using ref keyword. Here the variable gets updated in the called method and it shows 20 and 40 in output.

Note: ref keyword can be used with reference types as well. You can refer one of my previous posts for details here 

C# 7.0 Enhancements :

As in the example above, the values are passed by reference in the method but what about returning the values by reference. For this, there were two enhancements introduced

1- Ref Returns : For this, we need to add ref keyword after return statement in a method and before the return type in the method signature. This feature can be used only in Class (not structs). Let see the Point class as

public class Point
{
    private int x, y;

    public Point(int a, int b)
    {
        this.x = a;
        this.y = b;
    }
    public ref int GetX()
    {
        return ref this.x;
    }

    public ref int GetY()
    {
        return ref this.y;
    }
      
    public void Display()
    {
        Console.WriteLine($"Point coordinates x : {x}, y : {y}");
    }
}

Here I added two methods GetX and GetY which returns x and y by reference. ref keyword also got added with method signature as well.

2- Ref Locals: To store a reference variable (ref), returned by a method, the local variable should also be added with ref keyword before the type and adding the ref keyword before the method call. Now the local variable contains the value by reference and has the ability to change the value of variable which will reflect in the original variable as well. We can call the method without using the ref keyword which will behave as normal method call and the returned value will be a copy of the value.

static void Main(string[] args)
{
    Point p = new Point(10, 20);

    ref int i = ref p.GetX();
    i = 50;

    p.Display(); // Output: Point coordinates x : 50, y : 20

    int j = p.GetY();
    j = 100;

    p.Display(); // Output: Point coordinates x : 50, y : 20

    Console.ReadKey();
}

Initially the values of x and y are 10 and 20. We got the variable x by refernce and updated it to 50 using variable i which is reflected in output. We also received the value of y without using ref which creates a copy of the variable and updating it doesn’t affect the instance p.

It is a really nice feature in scenarios where the values are required to be updated at different places. This also can be when we have a collection of values and few of the items can be updated by the caller method based on the need.

Enhancements in Out parameter: There is a small enhancements in out parameter usage. Earlier out parameter is used as

static void Main(string[] args)
{
    int age;
    string name = GetUserDetails(out age);
    Console.WriteLine($"name : {name}, age : {age}");

    Console.ReadKey();
}

public static string GetUserDetails(out int age)
{
    age = 32;
    return "Brij";
}

Now after enhancement, we dont need to declare the variable first, instead we can direcly declare in the paarmeter as well as

static void Main(string[] args)
{
    //int age;
    string name = GetUserDetails(out int age);
    Console.WriteLine($"name : {name}, age : {age}");

    Console.ReadKey();
}

Although this is a small enhancement but makes more sense.

Hope you enjoyed the post and will be able leverage these enhancements in your day to day coding.

Cheers,
Brij

Leave a comment