Press "Enter" to skip to content

Month: January 2016

C# – Difference between passing variables by reference and by value

A reader recently asked about “pointers” in C++, and if we use them in C#. That led to the C# concept of variables being “reference types” or “value types” – which I’ll explain here.

 

Which variables are value type, and which are reference type?

When you create a variable, you declare its datatype. You can use the “var” keyword, instead of the datatype. However, the .NET compiler determines what the datatype is, and uses the actual datatype when it compiles your program.

Some datatypes (mostly the built-in .NET datatypes, like numbers and booleans) are value types. Others (strings, and the classes you create for your project) are usually reference types.

 

How do they act differently?

When you create (instantiate) a variable, it is placed at a location in memory.

If you copy a value type variable to another variable, the value of that variable is used, and gets its own new place in memory (for the new variable). This also includes when you pass a value type variable as a parameter in a function. The function copies the value from the original variable into the parameter variable.

So, if you make any changes to the second variable, it does not touch the original variable’s memory.

Here is a function showing what happens when a value type variable is copied to another variable:

private void ValueTypeVariableCopied()
{
   // An integer is a "value type" variable.
   int variable1 = 5;
   int variable2 = variable1; // Only copies the value "5" to variable2
   variable2 = 6;
   // The variable values are now:
   //     variable1 = 5
   //     variable2 = 6
}

 

This is what happens when a value type variable is passed to a function, and modified inside the function:

private void PassValueTypeVariableAsParameter()
{
   // Pass integer variable (value type)
   int variable = 5;
   IncrementValueTypeVariable(variable);
   // The variable value is now:
   //     variable = 5
}
private void IncrementValueTypeVariable(int parm)
{
   // The "parm" parameter received a value of 5,
   // not a pointer/reference to the calling variable.
   // So, any changes to "parm", do not affect the calling variable.
   parm = parm + 1;
}

 

When you copy a reference type variable (including passing it to a function), another instance of the variable is not created in memory. Instead, .NET passes a reference/pointer to the original variable’s location in memory.

Any changes you make to the new variable are made to the location in memory where the variable was originally created. So, if you look at the original variable, you will see that its value has changed.

Here is how a reference type variable is modified, when copied to another variable:

private void ReferenceTypeVariableCopied()
{
   // An object created from a custom class is a "reference type".
   // When you set it to another reference type variable,
   // the second variable does not make a copy of the first.
   // Instead, it points a "reference" to the original variable.
   // Anything you do to the second variable, goes to the one location in memory.
   MyClass variable1 = new MyClass();
   variable1.MyProperty = 5;
   MyClass variable2 = variable1; // Copies a reference/pointer to variable1
   variable2.MyProperty = 6;
   // The variable values are now:
   //     variable1.MyProperty = 6
   //     variable2.MyProperty = 6
}

 

And here is what happens when a reference type variable is passed to a function:

private void PassReferenceTypeVariableAsParameter()
{
   // Pass a reference type variable
   MyClass variable = new MyClass();
   variable.MyProperty = 5;
   IncrementReferenceTypeVariable(variable);
   // After calling the function:
   //     variable.MyProperty = 6
}
private void IncrementReferenceTypeVariable(MyClass parm)
{
   // The "parm" parameter is a reference/pointer to the calling variable.
   // So, any changes to "parm", will be done to the calling variable.
   parm.MyProperty = parm.MyProperty + 1;
}

 

Passing a value type variable as a reference

You can pass a value type variable to a function, and have it treated like a reference type – any modifications inside the function will happen to the original variable.

To pass a value type variable as a reference, you must include “ref” in the function’s parameter list, and when you call the function, like this:

private void PassValueTypeVariableAsParameterByReference()
{
   // Pass a value type variable, but as a reference
   int variable = 5;
   IncrementValueTypeVariableByReference(ref variable);
   // The variable value is now:
   //    variable = 6
}
private void IncrementValueTypeVariableByReference(ref int parm)
{
   // The "parm" parameter received a reference/pointer to the calling variable.
   // So, any changes to "parm", will also be seen in the calling variable.
   parm = parm + 1;
}

 

 

2 Comments