In the C++ language, there is a delete operator that allows the programmer to explicitly control when a dynamically allocated object is no longer needed, and its memory can therefore be recycled. This is both a blessing and a curse! It's a blessing, because it gives a C++ programmer very tight control over his/her memory resources in a program. But, if a C++ programmer forgets to recycle his/her objects, the program can literally run out of memory—this is known as a "memory leak."
With C#, however, there is no delete operator: anything dynamically created—i.e., everything but simple data types—is a candidate for C# garbage collection when all references to it (handles) have been eliminated. Like the "object as a helium balloon" example that we discussed in Chapter 3, when we let go of all strings on a balloon, it essentially floats away. Garbage collection is an automatic function performed by the C# runtime; when an object is garbage collected, the memory that was allocated to that object is recycled and added back to the pool of memory that is available to the runtime for new object creation.
By way of review, there are several ways to release handles on objects in C# so as to make them candidates for garbage collection, as the following example illustrates:
// Declare two reference variables to hold on to future // (as of yet to be created) Student objects. Student s1; Student s2; // Instantiate a Student object, and store a handle on this object in s1. s1 = new Student(); // Copy the handle into s2, so that we now have two handles on the same object. s2 = s1; // Let's now look at two different ways to "drop" an object reference. // We can reset a variable previously holding a handle to the value null ... s1 = null; // (We still have one of two handles left on the object.) // ... or we can hand a variable some OTHER object's handle, // causing it to drop the first handle. Here, by creating a // second Student object and handing it to s2, s2 drops the // only remaining handle on the first Student object. s2 = new Student( ); // No more handles on the original student remain!
We've eliminated all obvious references to the original instance of a Student; if there are no remaining references to an object, it becomes a candidate for garbage collection. We emphasize the word "candidate" in the previous sentence, however, because the garbage collector doesn't immediately recycle the object. Rather, the garbage collector runs whenever the runtime determines that there is a need for some recycling to be done, e.g., when the application is getting low on free memory necessary to allocate new objects. So, for some period of time, the "orphaned" Student object will still exist in memory—we merely won't have any handles with which to reach it.
The inclusion of garbage collection in C# has virtually eliminated memory leaks. Note that it's still possible for the runtime to run out of memory, however, if too many handles are maintained on too many objects; so, a C# programmer can't be totally oblivious to memory management—but it's far less error prone than with C/C++.