#218 – Store Value-Typed Objects on the Heap Through Boxing

Value-typed objects are typically stored on the stack, while reference-typed objects are stored on the heap.  You can, however, convert an instance of a value type to a reference type object through a process known as boxing.

In the example below, we box i, assigning it to a reference type variable.  Because i derives from System.Object (object), as do all types in .NET, we can assign i to o without doing a cast.  A new object is created on the heap, the value of i is copied into it, and the variable o is set to reference the new object.

            int i = 46;
            object o = i;   // Box i

Because a copy of the value-typed object is made, you can change the original object without changing the new object on the heap.

            i = 47;   // i now 47, but o still points to object with value of 46

#186 – Value Types on the Heap

Value types are normally allocated on the stack. They can, however, be allocated on the heap–when they are declared within an object.  When an object is instantiated, memory for the entire object, including all of its data, is allocated on the heap.

For example, assume we define a Person class with some properties that are value types (int) and some that are reference types (string).

    public class Person
        string FirstName;
        string LastName;

        int Age;
        int HeightInInches;      // also on heap

        public Person(string firstName, string lastName)
            FirstName = firstName;
            LastName = lastName;

When you create an instance of the Person object,

            Person p = new Person("Zsa Zsa", "Gabor");

the Person object is created on the heap and all of its data members, including the Age and HeightInInches value types, are also on the heap.

#67 – Default Behavior for Reference Type Equality

For reference types, a default equality check normally checks to see if the references are pointing to the exact same object–rather than checking to see if the objects pointed to are equivalent.

Suppose we have a Person type that has a constructor that takes Name and Age values.

 public class Person
     public string Name { get; set; }
     public uint Age { get; set; }

     public Person(string name, uint age)
         Name = name;
         Age = age;

Now suppose that we create two instances of the Person object with the same values for Name and Age.  The code fragment below shows what happens when we check to see if the resulting objects are equal.

 Person p1 = new Person("Sean", 46);
 Person p2 = new Person("Sean", 46);

 bool b = (p1 == p2);    // False, because p1 and p2 point to different objects

#44 – Multiple References to the Same Object

If you assign a variable that points to a reference type to another variable of the same type, both variables end up pointing to the same object in memory.  This means that changing the contents of the object through the first reference results in changes that are also seen by the second reference.

The following code:

 Person p1 = new Person("Sean", 46);     // New Person object
 Person p2 = p1;                         // Points to same object

Results in this situation:

Also, if we change one of the properties of the Person object using the p2 reference, we see the same change when using p1. This confirms that both variables are pointing to the same object.

 p2.Age = 50;
 int age = p1.Age;       // Also now = 50

#43 – Objects Are Instantiated on the Heap

When you instantiate a reference type using the new operator, you are creating a new instance of that type.  The object is created on what’s known as the managed heap.  In other words, memory is allocated to store the member data of the object and that memory is allocated from an area of memory known as the heap.

For example, when you execute the following line to create a new Person object:

  Person myPerson = new Person("Sean", 46);

You’ve created an instance of a Person, storing the data on the heap.  You’ve also created a reference variable, myPerson, that references (or points to) the new object.

#42 – Interacting with an Object

Once you create an instance of a reference type using the new keyword, you can interact with the new object through the variable that serves as a reference to that object.  You can call the object’s methods or read and write its properties.

 // Make a new Person object
 Person p1 = new Person("Sean", 46);

 // Read some properties
 string theName = p1.Name;   // Sean
 int howOld = p1.Age;        // 46

 // Set Age property to new value
 p1.Age = p1.Age - 10;
 int younger = p1.Age;       // Now 36

 // Call method that takes no parameters, returns description
 //   Will return:  Sean is 36 yrs old.
 string describe = p1.Description();

#41 – Instantiating Reference Types Using the new Keyword

To create an object of a particular type, you need to instantiate the type.  Value types are instantiated by assigning them a value.  Reference types are instantiated using the new keyword.  Using new allows us to create a new instance of the type.

When new is used to instantiate a type, the type’s constructor is called to perform the initialization.  The type may have a default constructor that takes no parameters, or it may have a constructor that takes one or more parameter values.  It may also support multiple constructors.

Variables declared as instances of reference types will hold the value null until they are instantiated.

 Person p1;     // Not instantiated, value is null

 // p2 points to new instance of the Person class
 //   Default constructor, takes no parameters
 Person p2 = new Person();

 // Construct another Person object using a
 //   different constructor, which takes Name and Age
 Person p3 = new Person("Sean", 46);