Free mag vol1 | Page 536

CHAPTER 13  UNDERSTANDING OBJECT LIFETIME Exactly how this garbage collection occurs, however, depends on which version of the .NET platform your application is running under. You’ll look at the differences a bit later in this chapter. Setting Object References to null C/C++ programmers often set pointer variables to null to ensure they are no longer referencing unmanaged memory. Given this, you might wonder what the end result is of assigning object references to null under C#. For example, assume the MakeACar() subroutine has now been updated as follows: static void MakeACar() { Car myCar = new Car(); myCar = null; } When you assign object references to null, the compiler generates CIL code that ensures the reference (myCar, in this example) no longer points to any object. If you once again made use of ildasm.exe to view the CIL code of the modified MakeACar(), you would find the ldnull opcode (which pushes a null value on the virtual execution stack) followed by a stloc.0 opcode (which sets the null reference on the variable): .method private hidebysig static void MakeACar() cil managed { // Code size 10 (0xa) .maxstack 1 .locals init ([0] class SimpleGC.Car myCar) IL_0000: nop IL_0001: newobj instance void SimpleGC.Car::.ctor() IL_0006: stloc.0 IL_0007: ldnull IL_0008: stloc.0 IL_0009: ret } // end of method Program::MakeACar What you must understand, however, is that assigning a reference to null does not in any way force the garbage collector to fire up at that exact moment and remove the object from the heap. The only thing you have accomplished is explicitly clipping the connection between the reference and the object it previously pointed to. Given this point, setting references to null under C# is far less consequential than doing so in other C-based languages; however, doing so will certainly not cause any harm. The Role of Application Roots Now, back to the topic o f how the garbage collector determines when an object is no longer needed. To understand the details, you need to be aware of the notion of application roots. Simply put, a root is a storage location containing a reference to an object on the managed heap. Strictly speaking, a root can fall into any of the following categories: • References to global objects (though these are not allowed in C#, CIL code does permit allocation of global objects) • References to any static objects/static fields • References to local objects within an application’s code base 477