.NET Type System, Part II
(Page 1 of 7 )
In this second part of the series, you will learn about reference types, especially arrays and strings. You will also learn how reference types work internally. You will be introduced to delegates and classes, too, as reference types, but they will be discussed in detail later.
Reference Types
Each time we declare a variable of a value type (like int32 variable) we know that this variable require four bytes to store its value. Because the value that will be stored in this variable is one piece of data, it is stored in-line with the variable (in the variable). This is fine, because copying operations on small values is not a big deal. For example, look at the following program:
using System;
namespace ValueTypes
{
class Class1
{
static void Main(string[] args)
{
int x = 45999;
int y = x; // the copying operation
Console.WriteLine(x);
Console.WriteLine(y);
Console.ReadLine();
}
}
}
As you can see, the value of the variable x is copied to the variable y. This happens because we know that any variable of type Int32 is four bytes. This is very different with reference types; when you define a class called Customer you don't know how many bytes you need to allocate for this class, so it's not a fixed size type. In fact, when you declare a variable, the CLR needs to know how many bytes of the memory this variable needs, in order to allocate the space.
So why is it that, though you don't know the size of the Customer class instance, the CLR will allocate space for it? The answer is, because it's a reference type. When you declare a variable of a reference type, the variable itself does not contain the value (unlike the value type); it contains a piece of data called a "reference" to where the value is actually stored.
The value is stored in a large piece of memory called the CLR Managed Heap. The Managed Heap is slower than the Stack in copying and allocating because of the semantics of reference types (the types are not fixed in size). We allocate objects on the Managed Heap and (unlike C++) the CLR will free the unused memory location as it is needed. Let's take a look at the Customer Example so you can better understand this concept:
class Customer
{
public string FirstName;
public string LastName;
}
For now this is a class that contains two member fields. Copy the following code and compile it.
using System;
namespace ReferenceTypes
{
class Class1
{
static void Main(string[] args)
{
Customer aCustomer = new Customer();
aCustomer.FirstName = "Michael";
aCustomer.LastName = "Youssef";
Console.WriteLine(aCustomer.FirstName + " " + aCustomer.LastName);
Customer AnotherCustomer;
AnotherCustomer = aCustomer;
Console.WriteLine(AnotherCustomer.FirstName + " " + AnotherCustomer.LastName);
Console.ReadLine();
}
}
class Customer
{
public string FirstName;
public string LastName;
}
}
The output of this code is
Michael Youssef
Michael Youssef
We simply created an instance of the Customer class using the new operator. The new operator created an instance of the reference type on the Managed Heap and returned a memory reference to it, so it may return something like 0x456454 and store it in the variable. The reference to the instance is stored in the variable aCustomer; we initialized the member fields with the FirstName Michael and the LastName Youssef. We used the Console.WriteLine() method to print these values to the console.
After that we declared another variable of type Customer, but for this variable we did not use the new operator to create another instance of the Customer class. We assigned the variable aCustomer (which contains the reference to the actual Customer instance) to the second variable AnotherCustomer, and again, we printed the FirstName and LastName of the AnotherCustomer object. As you can see, it's the same as the aCustomer object.
Why? I think it's pretty clear now that we assigned the reference to the memory address of aCustomer object to the variable AnotherCustomer, so both of them refer to the same object. So the assignment is AnotherCustomer = aCustomer; it just copies the aCustomer value (which is a reference to the memory where the actual object is allocated) to the AnotherCustomer variable, it doesn't do anything else. Now both variables refer to the same object in memory. So the instance in this example exists in one place (the Managed Heap) and is referenced by two variables (or as many as you need).
Next: C# Classes >>
More .NET Articles
More By Michael Youssef