I was looking for ways to do lazy initialization and found Lazy<T>
which is included in .NET 4.
I was thinking of rolling my own implementation of Lazy<T>
for .NET 3.5 (with a simpler multi-thread policy), and I bumped into the following problem:
Lazy has basically two types of constructors:
class Lazy<T> {
public Lazy(){...} // ctor #1
which uses T's default constructor for creating an instance of T, and
public Lazy(Func<T> func){...} // ctor #2
which lets the caller decide how the instance of T is created.
Now here's the problem:
If I want compile-time checking for the 1st ctor I will add a restriction
class Lazy<T> where T: new() {...}
at the class level. This will allow me to use new T()
to create an instance; but this restriction is not necessary for the 2nd ctor, and worse, it also restricts the types I can use (to those with a default ctor)
If I want to be able to use any type with the 2nd ctor, I will not set any restriction, and in the 1st ctor will use reflection to make sure T
does have a default ctor. This approach, however, will lack the compile-time check, and will only throw a runtime exception if the 1st ctor is used with the wrong type.
My question is: Can I get the best of both worlds?
Ideally, I would like to get the compile-time check for every use of ctor #1, but at the same time be able to use ctor #2 for types that don't have a default ctor.
How does the Microsoft implementation do this? (I don't readily have access to the .NET 4 sources or dlls).
EDIT: (After "Reflector-ing" the MS assembly)
I checked the reference implementation and it doesn't do compile-time checks.
It uses reflection for the 'default ctor' case, of course accompanied by the runtime exception if things go bad.
Why don't you just download the parallel extesions and install
Lazy<T>
for 3.5? Direct linkYou could use a static factory method instead of a overload to the constructor:
Now, this breaks compatibility (to some extent) with the .NET 4.0 version of
Lazy<T>
, but it does achieve compile time safety for both types of usage.You could make this a bit cleaner by making the constructors for
Lazy<T>
protected internal, and provide a static factory class that you always use to create instances:No.
Basically you have no compile time checkable constraint.
I expect the inbuilt implementation simply uses
Activator.CreateInstance<T>
for simplicity. The cleanest way I can think of cheating this is with a separate factory:Something like this should work for you. We used this in our local code base for a year or so before moving to 4.0.