I have a strange habit it seems... according to my co-worker at least. We\'ve been working on a small project together. The way I wrote the classes is (simplified example):<
Do you consider implementing such pattern using Lazy<T>
?
In addition to easy creation of lazy-loaded objects, you get thread safety while the object is initialized:
As others said, you lazily-load objects if they're really resource-heavy or it takes some time to load them during object construction-time.
Are you sure Foo should be instantiating anything at all?
To me it seems smelly (though not necessarily wrong) to let Foo instantiate anything at all. Unless it is Foo's express purpose to be a factory, it should not instantiate it's own collaborators, but instead get them injected in its constructor.
If however Foo's purpose of being is to create instances of type Bar, then I don't see anything wrong with doing it lazily.
The downside that I can see is that if you want to ask if Bars is null, it would never be, and you would be creating the list there.
I think it depends on what you are initialising. I probably wouldn't do it for a list as the construction cost is quite small, so it can go in the constructor. But if it was a pre-populated list then I probably wouldn't until it was needed for the first time.
Basically, if the cost of construction outweighs the cost of doing an conditional check on each access then lazy create it. If not, do it in the constructor.
It is a good design choice. Strongly recommended for library code or core classes.
It is called by some "lazy initialization" or "delayed initialization" and it is generally considered by all to be a good design choice.
First, if you initialize in the declaration of class level variables or constructor, then when your object is constructed, you have the overhead of creating a resource that may never be used.
Second, the resource only gets created if needed.
Third, you avoid garbage collecting an object that was not used.
Lastly, it is easier to handle initialization exceptions that may occur in the property then exceptions that occur during initialization of class level variables or the constructor.
There are exceptions to this rule.
Regarding the performance argument of the additional check for initialization in the "get" property, it is insignificant. Initializing and disposing an object is a more significant performance hit than a simple null pointer check with a jump.
Design Guidelines for Developing Class Libraries at http://msdn.microsoft.com/en-US/library/vstudio/ms229042.aspx
Lazy<T>
The generic Lazy<T>
class was created exactly for what the poster wants, see Lazy Initialization at http://msdn.microsoft.com/en-us/library/dd997286(v=vs.100).aspx. If you have older versions of .NET, you have to use the code pattern illustrated in the question. This code pattern has become so common that Microsoft saw fit to include a class in the latest .NET libraries to make it easier to implement the pattern. In addition, if your implementation needs thread safety, then you have to add it.
Obvioulsy, you are not going to use lazy-initialization for primitive data type or simple class use like List<string>
.
Lazy<T>
was introduced in .NET 4.0, so please don't add yet another comment regarding this class.
When you are building libraries, you must consider all optimizations. For instance, in the .NET classes you will see bit arrays used for Boolean class variables throughout the code to reduce memory consumption and memory fragmentation, just to name two "micro-optimizations".
You are not going to use lazy initialization for classes that are directly used by the user-interface. Last week I spent the better part of a day removing lazy loading of eight collections used in a view-model for combo-boxes. I have a LookupManager
that handles lazy loading and caching of collections needed by any user-interface element.
I have never used a set-property ("setters") for any lazy loaded property. Therefore, you would never allow foo.Bar = null;
. If you need to set Bar
then I would create a method called SetBar(Bar value)
and not use lazy-initialization
Class collection properties are always initialized when declared because they should never be null.
Let me repeat this differently, you use lazy-initialization for complex classes. Which are usually, poorly designed classes.
I never said to do this for all classes or in all cases. It is a bad habit.
Let me just add one more point to many good points made by others...
The debugger will (by default) evaluate the properties when stepping through the code, which could potentially instantiate the Bar
sooner than would normally happen by just executing the code. In other words, the mere act of debugging is changing the execution of the program.
This may or may not be a problem (depending on side-effects), but is something to be aware of.