CHAPTER 13 UNDERSTANDING OBJECT LIFETIME
private AllTracks allSongs = new AllTracks();
}
public AllTracks GetAllTracks()
{
// Return all of the songs.
return allSongs;
}
The current implementation of MediaPlayer makes the assumption that the object user will want to
obtain a list of songs via the GetAllTracks() method. Well, what if the object user does not need to
obtain this list? In our current implementation, the AllTracks member variable will still be allocated,
thereby creating 10,000 Song objects in memory, as follows:
static void Main(string[] args)
{
Console.WriteLine("***** Fun with Lazy Instantiation *****\n");
// This caller does not care about getting all songs,
// but indirectly created 10,000 objects!
MediaPlayer myPlayer = new MediaPlayer();
myPlayer.Play();
}
Console.ReadLine();
Clearly, you would rather not create 10,000 objects that nobody will use, as that will add a good deal
of stress to the .NET garbage collector. While you could manually add some code to ensure the allSongs
object is created only if used (perhaps using the factory method design pattern), there is an easier way.
The base class libraries provide a very useful generic class named Lazy<>, defined in the System
namespace of mscorlib.dll. This class allows you to define data that will not be created unless your code
base actually makes use of it. As this is a generic class, you must specify the type of item to be created on
first use, which can be any type with the .NET base class libraries or a custom type you have authored
yourself. To enable lazy instantiation of the AllTracks member variable, you can simply replace this:
// The MediaPlayer has-an AllTracks object.
class MediaPlayer
{
...
private AllTracks allSongs = new AllTracks();
}
public AllTracks GetAllTracks()
{
// Return all of the songs.
return allSongs;
}
with this:
// The MediaPlayer has-an Lazy object.
class MediaPlayer
{
...
497