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