Lazy intialization is a method used to set the values of objects at the latest possible moment (if at all.) The idea behind it is that it’s often hard to tell if and when an expensive operation needs to execute, so putting off until the result’s actually needed is going to save processing time. While it’s possible to implement lazy intialization in many languages, VB.NET provides a keyword that makes thread safe lazy intialization easy, and that’s the the Static keyword (this is different from Shared, or C#’s static.)
The Static keyword can be used in place of Dim when declaring a variable. The declaration of such variables can only be within the scope of a method. When applied to a variable, the variable retains its value after the method has finished executing, making it equivalent to a class level variable but only that one method can access it. From MSDN:
Normally, a local variable in a procedure ceases to exist as soon as the procedure stops. A static variable continues to exist and retains its most recent value. The next time your code calls the procedure, the variable is not reinitialized, and it still holds the latest value that you assigned to it. A static variable continues to exist for the lifetime of the class or module that it is defined in.
One of the implementation details of Static is that if the variable is initialized on the same line that it’s declared on, then it will be initialized once, and only once, in a thread safe manner. This is the key property that allows lazy intialization, I’ll now run you through an example to show you what I mean.
Say you have a class, in that class you’ve got several functions that need access to some data which is retrieved from the database. You’re not 100% sure what order the methods will execute in, and you’re not 100% sure that they’ll even need the data for a given execution, and you don’t want waste time loading the data in the constructor. Lazy initialization to the rescue! With a private, read only property that wraps a Static variable that’s initialized on the same line you magically have lazy initializaiton:
Public Class LazyInitialization Private ReadOnly Property Data() As DataSet Get Static _data As DataSet = DB.GetData() Return _data End Get End Property ' Some methods End Class
Now you can access the Data property from anywhere within your class, and know that’ll return the data to you safely.
To write something that’s more or less equivalent in C#, maintaining thread safety, you’d end up with something like this:
private object _lockObject = new object(); private DataSet _data; private DataSet Data { get { if (_data == null) { lock (_lockObject) { if (_data == null) { _data = DB.GetData(); } } } return _data; } }
While the C# version achieves basically the same thing, it lacks the benefit of encapsualting the data (what’s stopping a method for accessing the _data variable instead?) And it takes up twice as many lines to write.
The reason I say “basically the same thing” is that the actually implementation, post compiler magic, is quite a bit more complicated. Looking at the complied version of the VB code disassembled into C# with Red Gate’s .NET Reflector gives you the following, which I’ll leave you to discern at your leisure:
public class LazyInitialization { // Fields private DataSet $STATIC$get_Data$2001235$_data; private StaticLocalInitFlag $STATIC$get_Data$2001235$_data$Init = new StaticLocalInitFlag(); // Properties private DataSet Data { get { Monitor.Enter(this.$STATIC$get_Data$2001235$_data$Init); try { if (this.$STATIC$get_Data$2001235$_data$Init.State == 0) { this.$STATIC$get_Data$2001235$_data$Init.State = 2; this.$STATIC$get_Data$2001235$_data = DB.GetData(); } else if (this.$STATIC$get_Data$2001235$_data$Init.State == 2) { throw new IncompleteInitialization(); } } finally { this.$STATIC$get_Data$2001235$_data$Init.State = 1; Monitor.Exit(this.$STATIC$get_Data$2001235$_data$Init); } return this.$STATIC$get_Data$2001235$_data; } } }
This is my first time visit at here and i am truly pleassant to read all at single place.
When I originally commented I clicked the “Notify me when new comments are added” checkbox and
now each time a comment is added I get several emails
with the same comment. Is there any way you can remove me from that service?
Thanks!