#926 – How Memory Is Allocated for Objects on the Managed Heap

When your applications starts up, the Garbage Collector (GC) allocates some virtual memory to use as a managed heap.  It creates a pointer to the next available free space in the managed heap, which defaults to point to the beginning of the (empty) heap.

When you use the new operator to create a new reference-typed object, the Garbage Collector allocates space on the managed heap for your object as follows:

  • It uses the pointer to the next available space on the heap to determine where to store your object
  • It advances the next available free space pointer, based on the size of your object
  • It zeroes out memory for the new object
  • It passes back a pointer to the new object, which is then stored in the reference-typed variable that refers to your object
  • The object’s constructor executes, to initialize data members within the object

 

Advertisements

#570 – Assignment Compatibility for Reference Types

A reference type is assignment compatible if the value being assigned belongs to a type that is either the same as, or is a derived type of, the type of the storage location being assigned to.  You can assign a variable of type T to a storage location of type U if T is a narrower type than U, or is the same type as U.

Hound huck = new Hound("Huckleberry", 55);

// Since Hound is a sub-class of Dog, we can
// assign to a variable of type Dog
Dog dog1 = huck;

In this case, the variable of type Dog will still be pointing to an instance of a Hound.  The assignment doesn’t change anything about the object.

To see this, construct an instance of a Dog directly and then compare the objects.

// This one points to an actual Dog instance
Dog dog2 = new Dog("Just some dog", 2);

#271 – Passing a Reference Type as an Output Parameter

You can pass a reference-typed variable to a method as an output parameter, using the out keyword.  This indicates that the parameter is an output method.  For a reference type, this means that the method is expected to change the reference to point to a different object.

        public static void FindBallPlayingDog(out Dog fav)
        {
            fav = null;
            foreach (Dog d in AllDogs)
            {
                if (d.Motto.Contains("ball"))
                    fav = d;
            }
        }

When calling the method, we need to include the out keyword as a parameter modifier:

            Dog kirby = new Dog("Kirby");
            kirby.Motto = "Love chasing balls";

            Dog jack = new Dog("Jack");
            jack.Motto = "Sneak away when possible";

            Dog fav = jack;

            Dog.FindBallPlayingDog(out fav);   // Fav is now Kirby

#270 – Passing a Reference Type by Reference

When you pass a reference type by value to a method, you pass in a reference to the object.  The method can change the object, but can’t change the reference.

        public static void AnnotateMotto(Dog d)
        {
            // Change the dog's motto
            d.Motto = d.Motto + " while panting";
        }

You can also pass a reference type by reference, which means that the method can change not only the contents of the object pointed to, but change the reference, causing it to refer to a different object.

        public static void FindNewFavorite(ref Dog fav)
        {
            fav.Motto = "No longer the favorite";

            foreach (Dog d in AllDogs)
            {
                if (d.Motto.Contains("ball"))
                    fav = d;
            }
        }

Below is an example of calling this method.

            Dog kirby = new Dog("Kirby");
            kirby.Motto = "Retrieve balls";

            Dog jack = new Dog("Jack");
            jack.Motto = "Growl at people";

            Dog myFav = jack;
            Dog.FindNewFavorite(ref myFav);

            Console.WriteLine(myFav.Name);   // Kirby

#266 – You Can’t Prevent a Method from Changing the Contents of Reference Types

We saw that even when you pass a variable by value to a method, if that variable is a reference to an object, the method can change the contents of the object.

C# doesn’t have a built-in language construct that allows you to tell the compiler to prohibit a method from changing the contents of an object that a parameter references.  (In C++, we can do this with the const keyword).

In C#, if you want to prevent a method from changing an object, you need to first clone your original object and pass a copy of the object to the method. (You’ll want to make a deep copy of the object).

Here’s an example of using the DeepCopy<T> method to pass a copy of the object.

            kirby.BarkAt(DeepCopy<Dog>(jack));


#265 – Passing Reference Types by Value

Recall that by default parameters are passed by value to a method.  A copy of the variable is passed to the method, which means that if the method changes the parameter’s value, the change won’t be seen by the calling code.

If a parameter’s type is a reference type, however, what is passed by value to the method is a reference to the object.  This means that while the method can’t change the reference, it can change aspects of the object that is referenced.

As an example, assume that we have a Dog.BarkAt method that takes a reference to another Dog.  In the code below, the BarkAt method actually changes the target dog’s BarkPhrase.

        public void BarkAt(Dog target)
        {
            Console.WriteLine("I say {0} to {1}", BarkPhrase, target.Name);

            // I can change target dog's properties
            target.BarkPhrase = "I-am-a-dope";
        }

This change is seen by the calling code.

#227 – Instances of Classes Are Created on the Heap

Because they are reference types, instances of classes are stored on the heap.  When you instantiate (or create) an instance of a class, the actual object is created on the heap and you reference the newly created object with a variable whose type corresponds to the class’ type.  The variable that references the object is stored on the stack.

            // New Person object created on the heap
            // p variable is a stack-based reference to the new object
            Person p = new Person("Cary", "Grant");

Because a class object is created on the heap, you don’t destroy the object explicitly, but it is automatically garbage collected.  The object will be a candidate for garbage collection when there are no longer any variables that reference the object.

            p = new Person("Jimmy", "Stewart");

            // No variable references Cary Grant anymore,
            // so he can be garbage-collected.