A deep dive: Value and reference types in .Net

Explore value types and reference types in .Net and learn how and where they are stored

Value and Reference types in .NET

Value and Reference types in .NET

Types in Microsoft .Net can be either value type or reference type. While value types are stored generally in the stack, reference types are stored in the managed heap.

A value type derives from System.ValueType and contains the data inside its own memory allocation. In other words, variables or objects or value types have their own copy of the data.

A reference type, meanwhile, extends System.Object and points to a location in the memory that contains the actual data. You can imagine a reference type similar to a pointer that is implicitly dereferenced when you access them. The built-in reference types supported by C# include: object, string, and dynamic. All fundamental data types, Boolean, Date, structs, and enums are examples of value types. Examples of reference types include: strings, arrays, objects of classes, etc. To create reference types in C#, you can take advantage of these keywords: class, interface and delegate.

Note that unlike a reference type, you cannot derive from a value type, nor can you assign a null value directly to a value type. You can assign a null value to a value type only by taking advantage of nullable types -- a feature added to the newer versions of .Net Framework. When a value type is copied to another, the value is copied. Hence, you can manipulate the values in them independent of the other -- a change in one doesn't affect the other. On the contrary, when you copy a reference type to another, the reference is copied. If you change one of them, the other is also affected. As an example, if one of the reference is set to null, the other also becomes null.

Storage locations

The CLR stores objects in three types of storage locations -- the registers, the stack or the managed heap. While the short-lived objects are stored inside registers or stack, the long-lived objects are stored in the heap. As I mentioned earlier, value types are generally stored in the stack.

It's a common misconception that value types are always stored in the stack. I would rather say that value types can be stored in the stack when the variable is either a temporary variable or is a local variable and the JIT compiler decides not to enregister the value. In essence, the actual location of a value type depends on the implementation of the JIT compiler. Note that a value type can be stored in a stack frame, in the CPU register or even in the heap memory if the value type is contained inside an object, i.e., if it is a part of a reference type. On the contrary, reference types are stored in the GC heap. The reference is stored in a stack while the object is allocated in the heap.

Instances or references of a value type are stored in the stack, the register or in the heap depending on whether the life time of the instance or the reference is short lived or a long lived. A value type can reside on the stack if they are local variables and in the managed heap if they are fields of a class, i.e., they belong to or are a part of a reference type.

Passing by value and passing by reference

The following code listing illustrates how you can pass a variable to a method by value.

 static void Increment(int i)

        {

            i = i + 1;

        }

        static void Main()

        {

            int x = 1;

            Increment(x);

            Console.WriteLine("The value of x is: " +x);

            Console.Read();

        }

Note that you can pass a value type as a reference to a method by using the ref keyword. The following code listing illustrates this.

static void Increment(ref int i)

        {

            i = i + 1;

        }

        static void Main()

        {

            int x = 1;

            Increment(ref x);

            Console.WriteLine("The value of x is: " +x);

            Console.Read();

        }

When the above code is executed, the message "The value of x is: 2" will be displayed in the console.

Boxing and unboxing

The conversion of a value type to a reference type is known as boxing. Unboxing is just the opposite - it is defined as the process of conversion of a reference type to a value type. The following code snippet illustrates boxing and unboxing in C#.

int i = 100;

Object obj = i; //Boxing

i = (int) obj; //Unboxing

This article is published as part of the IDG Contributor Network. Want to Join?

From CIO: 8 Free Online Courses to Grow Your Tech Skills
Notice to our Readers
We're now using social media to take your comments and feedback. Learn more about this here.