I learned about Lazy class in .Net recently and have been probably over-using it. I have an example below where things could have been evaluated in an eager fashion, but that would result in repeating the same calculation if called over and over. In this particular example the cost of using Lazy might not justify the benefit, and I am not sure about this, since I do not yet understand just how expensive lambdas and lazy invocation are. I like using chained Lazy properties, because I can break complex logic into small, manageable chunks. I also no longer need to think about where is the best place to initialize stuff – all I need to know is that things will not be initialized if I do not use them and will be initialized exactly once before I start using them. However, once I start using lazy and lambdas, what was a simple class is now more complex. I cannot objectively decide when this is justified and when this is an overkill in terms of complexity, readability, possibly speed. What would your general recommendation be?
// This is set once during initialization.
// The other 3 properties are derived from this one.
// Ends in .dat
public string DatFileName
{
get;
private set;
}
private Lazy<string> DatFileBase
{
get
{
// Removes .dat
return new Lazy<string>(() => Path.GetFileNameWithoutExtension(this.DatFileName));
}
}
public Lazy<string> MicrosoftFormatName
{
get
{
return new Lazy<string>(() => this.DatFileBase + "_m.fmt");
}
}
public Lazy<string> OracleFormatName
{
get
{
return new Lazy<string>(() => this.DatFileBase + "_o.fmt");
}
}
This is probably a little bit of overkill.
Lazy should usually be used when the generic type is expensive to create or evaluate, and/or when the generic type is not always needed in every usage of the dependent class.
More than likely, anything calling your getters here will need an actual string value immediately upon calling your getter. To return a Lazy in such a case is unnecessary, as the calling code will simply evaluate the Lazy instance immediately to get what it really needs. The “just-in-time” nature of Lazy is wasted here, and therefore, YAGNI (You Ain’t Gonna Need It).
That said, the “overhead” inherent in Lazy isn’t all that much. A Lazy is little more than a class referencing a lambda that will produce the generic type. Lambdas are relatively cheap to define and execute; they’re just methods, which are given a mashup name by the CLR when compiled. The instantiation of the extra class is the main kicker, and even then it’s not terrible. However, it’s unnecessary overhead from both a coding and performance perspective.