Reputation: 13923
What are the differences between LazyInitializer and Lazy<T> classes? I know they both will initialize the object only on demand. When do I need to use each of them?
Upvotes: 44
Views: 15383
Reputation: 24480
One important consideration is what happens when multiple threads try to access an uninitialized value. With Lazy you get locking to ensure only one thread runs the initialization code. With LazyInitialization all threads will run the initialization code, with one result being kept and the rest thrown out. So in the first case you reduce the potential initialization cost, in the later case you reduce the longer-term synchronization costs.
Note that Lazy can be configured to behave like LazyInitialization be specifying a LazyThreadSafetyMode, though its not clear it would reap the full benefit of reduced locking.
Upvotes: -1
Reputation: 62504
Lazy<T>
(MSDN) is a generic wrapper which allows creating an instance of T
on demand by holding a T
factory method (Func<T>
) and calling it when Value
property getter is accessed.
LazyInitializer
- static class with a set of static methods, this is just a helper which uses Activator.CreateInstance() (reflection) able to instantiate a given type instance. It does not keep any local private fields and does not expose any properties, so no memory usage overheads.
Worth noting that both classes uses Func<T>
as instance factory.
MSDN says in few words about LazyInitializer
class:
These routines avoid needing to allocate a dedicated, lazy-initialization instance, instead using references to ensure targets have been initialized as they are accessed.
PS:
I found interesting a way how LazyIntiializer
checks whether instance already initialized, it just compare a passed in reference to a default(T)
, nice:
private static T EnsureInitializedCore<T>(ref T target, Func<T> valueFactory)
where T : class
{
T t = valueFactory();
if (t == null)
{
throw new InvalidOperationException(Environment.GetResourceString("Lazy_StaticInit_InvalidOperation"));
}
Interlocked.CompareExchange<T>(ref target, t, default(T));
return target;
}
What seems strange to me, it creates a new instance each time before an actual check:
T t = valueFactory();
// ... and only then does check
Upvotes: 23
Reputation: 59
As the other answers say,
Lazy<T>
Typically gives cleaner code: Just initialize with x = new Lazy<T>(_ => new ...)
and use x.Value
everywhere you access it.
Allows different, predefined options for handling initialization and exceptions if multiple threads access the Value
property of an uninitialized Lazy<T>
object concurrently.
LazyInitializer
Saves space and possibly also time: No need to initialize a new Lazy<T>
object for every variable you declare.
Allows you to delay providing initialization parameters until use time: LazyInitializer.EnsureInitialized(ref x, () => new X(initParameters))
In conlusion, you only need to use LazyInitializer
if space (and possibly time) is limited, or if you cannot specify all initialization parameters at declaration time.
Personally I prefer Lazy<T>
whenever possible, because I find it gives cleaner code, and I don't have to handle initialization exceptions explicitly myself.
Upvotes: 5
Reputation: 29
I think this answered your question: Another way of LazyInitialization System.Threading.ThreadLocal
It is the same as Lazy, but the only difference is that it stores data on Thread Local basis. So the values on the each Thread would be a different copy of the Initialized object.
more details from: http://www.cshandler.com/2011/09/different-ways-of-lazy-initialization.html
Upvotes: 1
Reputation: 3289
I'm not sure if you're still looking into this, but I've had to delve into the details of both Lazy<T>
and LazyInitializer.EnsureInitialized<T>()
recently, so I thought I should share my findings.
First, some numbers. I ran benchmarks using both methods on batches of ten million values using both approaches, testing for memory use with GC.GetTotalMemory(true)
and getting Stopwatch
timings for instantiation, first value access, and subsequent value accesses:
Lazy<T> Memory Use: 320,000,000 bytes (32B/instance)
EnsureInitialized<T>() Memory Use: N/A
Lazy<T> Instantiation Time: 622.01 ms
EnsureInitialized<T>() Inst. Time: N/A
Lazy<T> First Access: 1,373.50 ms
EnsureInitialized<T>() First Access: 72.94 ms
Lazy<T> Subsequent Accesses: 18.51 ms
EnsureInitialized<T>() Subsequent: 13.75 ms
(I used LazyThreadSafetyMode.PublicationOnly
with the Lazy<T>'s
, which looks to be the same thread safety approach taken by LazyInitializer
by default.)
As you can see, unless I've screwed up my tests somehow (never out of the question!), under these circumstances LazyInitializer
is superior in just about every quantifiable way. It has no memory or instantiation overhead, and it's faster both for creating and retrieving the value.
So, why would you want to use Lazy<T>
? Well, first, these were the test results on my x64 system, and it's possible you might get different results under other circumstances.
Lazy<T>
can also result in clearer and more concise code. return myLazy.Value;
is a lot friendlier than return LazyInitializer.EnsureInitialized(ref myValue, () => GetValue(foo));
Additionally, Lazy<T>
makes things a lot simpler if you're dealing with a value type, or with a reference type that could legitimately be null
. With LazyInitializer
, you have to use a second boolean field to keep track of whether the value has been initialized, compounding the code clarity issue. Lazy<T>
is also simpler to use if you want stricter thread safety.
And in the grand scheme of things, most of the overhead is probably negligible for a lot of applications (although not always -- the reason I started looking into this is because I was working on an application involving millions of very small lazily-loaded values, and the 32-byte-per-instance overhead of Lazy<T>
was actually starting to become inconvenient).
In the end, unless your application is very memory-intensive, I think it's usually going to be a matter of personal preference. For non-null reference types, I personally think LazyInitializer.EnsureInitialized<T>()
is a more elegant approach, but I can dig the code clarity argument too.
Upvotes: 45
Reputation: 13215
The documentation on Lazy Initializing explains it pretty clearly. See Lazy Initialization. In short, Lazy<T>
creates a new class (a constructed generic) for every T
that you use, and a new instance of that class for every T
instance you decalre -- even if the underlying T
is never initialized. Using the static methods of LazyIntializer
can be more complex for coding but avoids overhead of the Lazy<T>
wrapper instances.
Upvotes: 1
Reputation: 19416
LazyInitializer
allows you the lazy initialization functionality without the overhead of creating a class for each lazily initialised object.
Here are the benefits LazyInitializer
can provide.
It will be up to your own requirements as to whether the overhead created by using Lazy<T>
is too much for the situation.
Upvotes: 2
Reputation: 1058
`LazyInitializer` of an object means its object creation is deferred until it is ued first.
An object of this form is created to improve performance and reduce memory wastage..
Whereas To Define a Lazy-initialized type we use Lazy<T>
(generic Form) of LazyInitializer
class
E.g:
Lazy<Orders> _orders = new Lazy<Orders>();
For Further References:
http://msdn.microsoft.com/en-us/library/dd997286.aspx
Upvotes: -1