In simple words, all value based types are allocated on the stack, while all reference based types are allocated on the heap. A value type contains the actual value. A reference type contains a reference to the value. When we assign a value type to another value type, a field-by-field copy is made. When we copy a reference type to another reference type, only the memory address is copied.

By saying stack, we mean things are kept one on top of the other. We keep track of each value at the top. By saying heap, we mean things are kept in a mashed order. We keep track of each value by its address, that is referenced by a pointer to it.

All value types are implicitly derived from System.ValueType. This class actually overrides the implementation in System.Object, the base class for all objects which is a reference type itself.

Data types like integers, floating point numbers, character data, Boolean values, Enumerations and Structures are examples of Value Types.

Classes, Strings, Arrays are examples of Reference Types.

A value type may not contain NULL values. Reference types may contain NULL values.

It is not possible to derive new types from Value Types. This is possible in Reference types. However, Value Types like Structures can implement interfaces.

class Program
{
static void Main(string[] args)
{
// Pass reference type by value
ArrayList arrayList = new ArrayList() { 0, 1, 2, 3 };
Console.WriteLine(“Pass by Value”);

PassByValue(arrayList);

// What should be the output of below line ??
Console.WriteLine(arrayList[1]);
arrayList = new ArrayList() { 0, 1, 2, 3 };
Console.WriteLine(“Pass by Reference”);
PassByReference(ref arrayList);
// What should be the output of below line ??
Console.WriteLine(arrayList[1]);
Console.Read();
}
private static void PassByValue(ArrayList arrayList)
{
Console.WriteLine(arrayList[1]);
// Now Change the first position value
arrayList[1] = 90;
arrayList = new ArrayList() { 101, 102, 103, 104 };
Console.WriteLine(arrayList[1]);
}
private static void PassByReference(ref ArrayList arrayList)
{
Console.WriteLine(arrayList[1]);
// Now Change the first position value
arrayList[1] = 90;
arrayList = new ArrayList() { 101, 102, 103, 104 };
Console.WriteLine(arrayList[1]);
}
}

Interpretation:

First we’ll take the case of passing value types by reference.

Let’s have a look at the PassbyValue function:

The first line of code obviously would look out for value placed at second index in the arrayList and print out 1. After that, we change the value present at second index to 90. In the third line, since we had passed the reference type by value; it created a copy of original memory block pointing to the original memory location. But as soon we re-create the object, this loses the reference to the original memory location and acts as a different arrayList object then onwards. However, the changes done to the arrayList before the re-creation of object still persists. That’s why, when we try to access the second index value, after the PassByValue function, we still get the output as 90.

Now, let’s have a look at the Pass by Reference function:

Here too the first line of code output would be the same as reflected by the PassByValue function. The second would again change the value present at the second index to 90. In the third line, since we had passed the reference type by reference, it would just re-initialize its value to the new array (note that here the original memory location is getting new values overwritten here), thus the value for arrayList[1] inside the function would be 102 and after that the newly changed array would be referred everywhere, even outside the function.

Output:

Pass By Value
1
102
90
Pass By Reference
1
102
102

Conclusion:

Passing reference types by Value creates a copy of the memory location and thus it is possible to change the value of the original reference type object inside the function (as soon we re-create that object). Passing reference types by ref doesn’t create any copy of the object; it impacts the original reference object.

Advertisements