Free mag vol1 | Page 558

CHAPTER 13  UNDERSTANDING OBJECT LIFETIME would have it, the Lazy<> class allows you to specify a generic delegate as an optional parameter, which will specify a method to call during the creation of the wrapped type. The generic delegate in question is of type System.Func<>, which can point to a method that returns the same data type being created by the related Lazy<> variable and can take up to 16 arguments (which are typed using generic type parameters). In most cases, you will not need to specify any parameters to pass to the method pointed to by Func<>. Furthermore, to greatly simplify the use of the required Func<>, I’d recommend using a lambda expression (see Chapter 10 to review the delegate/lambda relationship). With this in mind, the following is a final version of MediaPlayer that adds a bit of custom code when the wrapped AllTracks object is created. Remember, this method must return a new instance of the type wrapped by Lazy<> before exiting, and you can use any constructor you choose (here, we are still invoking the default constructor of AllTracks). class MediaPlayer { ... // Use a lambda expression to add additional code // when the AllTracks object is made. private Lazy allSongs = new Lazy( () => { Console.WriteLine("Creating AllTracks object!"); return new AllTracks(); } ); public AllTracks GetAllTracks() { // Return all of the songs. return allSongs.Value; } } Sweet! Hopefully you can see the usefulness of the Lazy<> class. Essentially, this generic class allows you to ensure expensive objects are allocated only when the object user requires them. If you find this topic useful for your projects, you might also want to look up the System.Lazy<> class in the .NET Framework 4.5 SDK documentation for further examples of how to program for “lazy instantiation.”  Source Code The LazyObjectInstantiation project is included under the Chapter 13 subdirectory. Summary The point of this chapter was to demystify the garbage collection process. As you have seen, the garbage collector will only run when it is unable to acquire the necessary memory from the managed heap (or when a given AppDomain unloads from memory). When a collection does occur, you can rest assured that Microsoft’s collection algorithm has been optimized by the use of object generations, secondary threads for the purpose of object finalization, and a managed heap dedicated to hosting large objects. 499