C# – There is no “Pass by Reference” without ref keyword

One common question that I see on Stack Overflow is about parameter passing in C#. A common statement for parameter passing sounds like:

Reference types are passed by reference and value types are passed by value

This is incorrect.

Before jumping on the details for parameter passing, I would ask you to visit this excellent article by Jon Skeet on parameter passing in C#. 

I will concentrate on parameter passing with reference types, as this is the main reason for confusion.

Consider the following example

using System;
namespace TestApplication
{
	class Program
	{
		static void Main(string[] args)
		{
			Person personMain = new Person { Name = "X", Id = 1 };
			ModifyPersonObject(personMain);
			Console.WriteLine(personMain.Name);	// prints "New Person Name"

			ModifyPersonObjectFail(personMain);
			Console.WriteLine(personMain.Name);	// still prints "New Person Name"

			Console.ReadLine();
		}

		static void ModifyPersonObject(Person person)
		{
			person.Name = "New Person Name";
		}

		static void ModifyPersonObjectFail(Person person)
		{
			person = new Person { Name = "Some Name", Id = 2 };
		}
	}

	class Person
	{
		public int Id { get; set; }
		public string Name { get; set; }
	}

}

In the above code a person object is created with initial values as “Name: X and Id: 1”. Then a method is called which is suppose to modify that person object. That method receives a paramter of type “Person” and modifies its Name property. The effect is visible after the call to method is completed.

Next, that object is send to another method which is suppose to assign a completely new “Person” object to it. But that fails and after the call to “ModifyPersonObjectFail” method is completed, the object “personMain” is still holding hold values.

Why is this happening.

A reference is kind of a pointer to some memory location holding the actual data. For example in our above code “personMain” is a reference which is pointing to a person object in memory with values Name: X and Id: 1. So in the first method call: “ModifyPersonObject(personMain);”, the parameter in the method is pointing to same memory location.

Step1

So, both “personMain” and “person” (parameter) are pointing to same location, thus changing “Name” property in the method actually modifies the value in object storage memory. .

Next is the method call to “ModifyPersonObjectFail(personMain);”, At the entry point in the method, both “personMain” and paramter “person” is pointing to same object, just like the diagram above, but this method has a line:

person = new Person { Name = "Some Name", Id = 2 };

which is assigning a new object to the parameter “person”. Now here is the important part, this line is actually creating a new object in object storage memory and assigning its address/reference  to the parameter. The original object in memory remains unaffected.

step2

Therefore, when the call to method “ModifyPersonObjectFail” is completed the original object in the caller remains unaffected.

So to conclude here is the main statement

There is no pass by reference in C# without “ref” keyword. In parameter passing address of the object (or reference) is only passed.

If you have method like:

static void ModifyPersonObjectByReference(ref Person person)
{
	person = new Person { Name = "Some Name", Id = 2 };
}

and then call that method like:

static void ModifyPersonObjectByReference(ref Person person)
{
	ModifyPersonObjectByReference(ref personMain);
}

then this would be somewhat pure pass by reference, as now even assigning a new value to parameter would be visible in caller.

Advertisements

One thought on “C# – There is no “Pass by Reference” without ref keyword

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s