Everything can be improved.
C. W. Barron

The human race has improved everything, but the human race.
Adlai Stevenson

Conversation would be vastly improved by the constant use of four simple words: I do not know.
Andr

In a previous blog entry, I discussed Lazy Loading.  With the release of Microsoft .NET 4 Framework, there is a new class to handle Lazy Loading.  It is called System.Lazy<T>

There are three advantages and two concerns that come to mind.  This blog entry to explore this new class and whether I will use it in future code.

Advantages

  • User has control of threading mode
  • Can check existence of value without executing Lazy Loading code.
  • Can pass generic to methods.

Concerns

  • Throwing Exception inside Lazy Loading Func<T> method means the Lazy property will cache exception unless thread mode is PublicationOnly.  See Microsoft documentation for more info.
  • Anonymous Method, Func<T>, passed in Lazy<T> constructor, can only see static properties and methods.  Many times, I have Windows Forms with simple Lazy Loaders that are sub-sets of application wide static Lazy Loaders.

Create a simple Windows Forms Application.  Two buttons and a text box.  One button shows the availability of the Lazy Load Property data.   The other button attempts to copy the Lazy Load Property data to the text box.  An exception is thrown the first time and then succeeds every time after.

The C# code below shows the Lazy Property with a thread mode of PublicationOnly highlighted and the anonymous method pass to the Lazy Constructor.  Full name spaces are used so there is no confusion where the class comes from.

private System.Lazy<string> LazyValue = new System.Lazy<string>(() =>
{
  if (!ConfigInfo.ErrorFree)
  {
    ConfigInfo.ErrorFree = true;
    throw new Exception("Forced Error");
  }

  if (!ConfigInfo.SimulateDbConnect(2))
    throw new System.Data.DataException("Never see this error");

  return ConfigInfo.SimulateDbData();

}, System.Threading.LazyThreadSafetyMode.PublicationOnly);

Click button Lazy Created? The following code is executed and the message box shows that the Lazy Load Property has not been filled.  This also shows the ability to pass a Lazy Property to a generic method is highlighted.

public bool IsLazyPropertyCreated<T>(System.Lazy<T> lazyProperty)
{
  return lazyProperty.IsValueCreated;
}

private void btnLazyCreated_Click(object sender, EventArgs e)
{
  MessageBox.Show("Lazy Value Created? - " +
    IsLazyPropertyCreated(LazyValue).ToString(),
    "LazyValue", MessageBoxButtons.OK, MessageBoxIcon.Information);
}

Click Show Lazy button twice.  The first time, a Forced Exception is thrown.  The second time, the Lazy Load is Successful.   The code and screen shots are shown below.

private void btnShowLazy_Click(object sender, EventArgs e)
{
  try
  {
    txtLazyValue.Text = LazyValue.Value;
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message, "LazyValue", MessageBoxButtons.OK, MessageBoxIcon.Error);
  }
}



Click Lazy Created? button again. Shows true now.

Should I use the new Lazy<T> class?

  • Yes if thread safety is important
  • Yes if the lazy load status is needed prior to loading.
  • No if class instance properties, fields or methods are needed in the Lazy load initialization code.
  • Probably No if Lazy load initialization code can throw an exception.
  • Probably No if the public Property exposed to the end user is object T instead of Lazy<T>

I prefer the old way instead of the new.  I like having more control over the initialization code, use either static or instance, and frequently Lazy Loading is used with a database and exceptions are sometimes thrown.

// New Way
private Lazy<string> _NewLazy = new Lazy<string>(() => GetLongRunningString());
public string NewLazy {get { return _NewLazy.Value; } }

// Old Way
private string _OldWay;
public string OldWay
{
  get
  {
    if (_OldWay == null)
      _OldWay = GetLongRunningString();

    return _OldWay;
  }
}

Download Solution

Tags: ,

Leave a Reply


*