Reputation: 6575
Can someone please explain in simple words, why does Lazy in C# needs to get Func?
public Lazy (Func<T> valueFactory);
I understand that sometime you need a function in order to do some fancy init().
however, many times I find myself writing a singleton, or something simple, where just create a new instance of the class.
As shown in Jon's Skeet book.
http://csharpindepth.com/Articles/General/Singleton.aspx
I find this syntax to be very annoying.
Thanks!
private static readonly Lazy<Singleton> lazy =
new Lazy<Singleton>(() => new Singleton());
Upvotes: 4
Views: 2593
Reputation: 431
Lazy
needs a Func
to actually initialize the inner value. the whole purpose of using Lazy is initializing a value only when its needed. so there should be a way Lazy to actually initialize the value when needed, that's where the Func
comes in. i don't see any other way to implement something like Lazy
other than passing a initialization function.
Upvotes: 1
Reputation: 156968
You can't get the Lazy
to work without the initializer function. That is how it ensures the logic for the creation of the object is there, but not yet called.
Consider this:
new Lazy<Singleton>(new Singleton());
This already instantiates a new Singleton
. There is no use for the lazy any more. The function allows Lazy<T>
to construct the object at any time in the future.
Another plus for the Func<T>
is that it doesn't need to be a new object it instantiates. It can be anything else. It can be a multi-line statement, a fetch of something else, etc.
One optimization I could argue for is that new Lazy<T>()
would use the new()
on T
, which prevents the need for you to call the constructor. That is however not possible with the current syntax, but it works with a static factory method.
Something like this (and yes, it is basically does what you do now, but then tucked away in the core):
public static class LazyDefault
{
public static Lazy<TNew> New<TNew>() where TNew : new()
{
return new Lazy<TNew>(() => new TNew());
}
}
Or as CodeCaster suggested with a derived class:
public class SuperLazy<T> : Lazy<T>
where T : new()
{
public SuperLazy()
: base(() => new T())
{
}
}
Upvotes: 6
Reputation: 64923
What you give to Lazy<T>
constructor is known as a thunk (Wikipedia):
In computer programming, a thunk is a subroutine used to inject an additional calculation into another subroutine. Thunks are primarily used to delay a calculation until its result is needed, or to insert operations at the beginning or end of the other subroutine. They have a variety of other applications in compiler code generation and modular programming.
That is, the core of lazy evalutation is that the whole thing to be evaluated is delayed until it's really required.
If you find annoying having to explicitly provide the Func<T>
, you may simplify that in the following way:
public static class Lazy
{
public static Lazy<T> Of<T>()
where T : class, new() => new Lazy<T>(() => new T())
}
var lazyFoo = Lazy.Of<Foo>()
Upvotes: 1
Reputation: 151584
You need a func, because if you could do this:
var Lazy<Foo> = new Lazy<Foo>(new Foo());
You're already instantiating the Foo
, which you don't want, otherwise you didn't have to use Lazy<T>
to begin with.
The Func<T>
holds the initializer for Foo
, but only initializes it when you access the Lazy<T>
's Value
.
Upvotes: 7