In this chapter, we have examined in detail how to get the best from the garbage collection facilities offered by the .NET Framework. We've investigated the advantages of garbage collection over other memory cleanup techniques, and looked at the internal workings of the garbage collector, including the way that it uses generations as a way to optimize performance and how it deals with finalizers. We then went on to discuss the situations in which you will need to write separate finalizers or Dispose() methods for your classes, as well as the techniques you should use to implement these methods in a way that doesn't adversely affect the garbage collection process too much. Finally, we saw how you can use weak references to provide an additional means to free up resources.