Thursday, 30 July 2015

Value and Reference Types - Stack vs Heap in .Net

Value and Reference Types :

When ever we declared any variable in .Net whether it is primitive data type or a custom data type(Instantiate a class), part of memory is allocated to store the value of this variable.

If variable is a value type, a single space in memory is allocated to store the value of this variable.Struct is value type in .Net.

With reference type, however, an object is created in memory, and then handled through a separate reference, means two separate memories are allocated.

Stack and Heap are the two memory management techniques used by .Net. 

Whenever we declare Struct type in .Net, memory for these variables will be allocated in stack.
Variable like int, float, double, byte, bool etc. all are of type Struct so memory for these variables also stored in stack.
The Stack is self-maintaining, meaning that it basically takes care of its own memory management. When the top box is no longer used, it's thrown out.

Any class, delegates, interface, string ,object and array are the reference type and stored in heap.
Two different memories are allocated for reference variable, one in a heap that store object and other memory contain reference of this heap memory and itself stored in stack.

Unlike stack, heap doesn't have any restriction to access the memory.any memory cab be accessed randomly.

Note 1 : As we already know, System.Object is the ultimate base class of all classes in the .NET Framework; it is the root of the type hierarchy.
Any variable that has Object class as it's root base class, will be type of reference variable.


Note 2 : Any reference type variable stored in a Heap. Whereas, where value type variable will store depends on where it is declared.If value type variable used with in a class, when we create the object of that class, value type variable will be stored within Heap other wise it will stored within Stack.

Suppose Address is a struct, and Employee is a class. We can instantiate each as follows:

Address a1 = new Address();        // Address is a *struct*
Employee e1 = new Employee();   // Employee is a *class*

In the first case, one space in memory is allocated for a1, wheras in the second case, two spaces are allocated: one for a Employee object and another for its reference (e1).

Employee e1;                   // Allocate the reference
e1 = new Employee ();     // Allocate the object

If we copy the objects to new variables:

Address a2 = a1;
Employee e2 = e1;

a2, being a struct, becomes an independent copy of a1, with its own separate fields. But in the case of e2, all we’ve copied is a reference, with the result that both e1 and e2 point to the same object.

When passing parameters to methods. In C#, parameters are (by default) passed by value, meaning that they are implicitly copied when passed to the method. For value-type parameters, this means physically copying the instance (in the same way a2 was copied), while for reference-types it means copying a reference (in the same way e2 was copied). Here is an example:

Address myAddress = new Address ("delhi", 110096);      // a new value-type variable
Employee myEmployee = new Employee ();         // a new reference-type variable
Test (myAddress , myEmployee );        // Test is a method defined below

void Test (Address a, Employee e)
{
a.City = "Mumbai";             // No effect on MyAddress since a is a copy
e.Name = "TestName";       // This will change myEmployee’s name since
                                           // myEmployee and e point to the same object
e = null;                               // No effect on myEmployee
}

Assigning null to e has no effect because e is a copy of a reference, and we’ve only erased the copy.

We can change the way parameters are marshalled with the ref modifier. When passing by “reference”, the method interacts directly with the caller’s arguments. In the example below, you can think of the parameters a and e being replaced by myAddress and myEmployee:

Address myAddress = new Address ("delhi", 110096); // a new value-type variable
Employee myEmployee = new Employee ();                 // a new reference-type variable
Test (ref myAddress, ref myEmployee);                   // pass myAddress and myEmployee by reference

void Test (ref Address a, ref Employee e)
{
a.City = "Mumbai";                // This will change myAddress’s City
e.Name = "TestName";          // This will change MyEmployees’s Name
f = null;                                  // This will nuke the myEmployees variable!
}

In this case, assigning null to e also makes myEmployee null, because this time we’re dealing with the original reference variable and not a copy of it.

No comments:

Post a Comment