C#, is there even a need to pass an object by reference?

Viewed 428

I am trying to refresh my understanding of C#. I have used Java before and passing by reference is a powerful tool that I truly miss in Java. However, I needed clarification if there is even a need to pass an object by reference and if there is a scenario where it may be helpful? Stackoverflow already has multiple questions around reference and they were truly enlightening, however, I was wondering if there is a scenario for passing objects by reference. Let me attach the code to better illustrate it.

class Program
    {
        public static void Update(int x) { x++; }
        public static void Update(ref int x) { x++; }
        public static void Update(Employee x) { x.msalary += 2000; }
        public static void Update(ref Employee x) { x.msalary += 2000; } //Do we even need this method? Is there a scenario where we might need this?

        static void Main(string[] args)
        {

            int a = 0;

            Update(a);
            Console.WriteLine("T1  " + a.ToString()); //a is still 0

            Update(ref a);
            Console.WriteLine("T2  " + a.ToString());//a is 1

            Employee emp2 = new Employee("Brent", "1234", "Blue", 1000); //salary is 1000

            Update(emp2.msalary);
            Console.WriteLine("T3  " + emp2.msalary.ToString());//salary does not change.

            Update(ref emp2.msalary);
            Console.WriteLine("T4  "+emp2.msalary.ToString());//salary changes to 1001

            Update(emp2);
            Console.WriteLine("T5  " + emp2.msalary.ToString()); //This changes, as expected for objects.

            Update(ref emp2);
            Console.WriteLine("T6  " + emp2.msalary.ToString()); //This also changes. But is there a scenario where we might need this?


        }
    }
1 Answers

Calling it "ref" was in my opinion a mistake; the right way to think of this feature is that it makes a local or parameter an alias to another variable. That is, when you use ref you have just given another name to an existing variable.

So the question then is: under what circumstances does it make sense to modify someone else's variable? Those are the circumstances in which you should use ref.

Back in historical times the main use case for ref was something like bool TryParse(string s, out int x) where you want to have two return values: a bool and an int. But that method was created in the C# 1 days before generics, nullables and tuples. The better practice now is: if you need to return a value type that could be invalid, return a nullable, and if you need to return two values, return a tuple. (Remember, out is just ref that requires writing before reading.)

What then is the current use case for ref in new code that uses tuples and nullable value types? There are some algorithms where you can gain a small amount of performance by reading and modifying a variable in another part of the data structure directly, but you need to pass around which variable needs reading and modifying. That is, ref should be used as a performance optimization for the implementation details of certain data types. (Remember that you cannot permanently store refs; you can only make a local an alias to another variable, and that local cannot have its lifetime extended! This greatly limits the use cases for refs.)

You can also use ref as a more clean, type-safe way to interoperate with unmanaged code that uses pointers as aliases for variables.

That's about it. I almost never use ref in mainstream, line-of-business code. It's there for when you need it, but you almost never do.

Related