Example 1 (does not compile):
void Main()
{
var c = new C<D>();
c.M.F();
}
class C<T>
{
T _m = null;
public T M { get {
if(_m == null) _m = new T();
return _m;
} }
}
class D
{
public void F() { Console.WriteLine ("i was created"); }
}
Result:
Cannot create an instance of the variable type 'T' because it does not have the new() constraint
Example 2 (works):
void Main()
{
var c = new C<D>();
c.M.F();
}
class C<T>
{
Lazy<T> _m = new Lazy<T>();
public T M { get { return _m.Value; } }
}
class D
{
public void F() { Console.WriteLine ("i was created"); }
}
Result:
i was created
The Lazy<T> object ensures that all threads use the same instance of the lazily initialized object and discards the instances that are not used. Thus, the cost of reducing the locking overhead is that your program might sometimes create and discard extra copies of an expensive object.
By default, Lazy<T> objects are thread-safe. That is, if the constructor does not specify the kind of thread safety, the Lazy<T> objects it creates are thread-safe.
Remarks. Use lazy initialization to defer the creation of a large or resource-intensive object, or the execution of a resource-intensive task, particularly when such creation or execution might not occur during the lifetime of the program. To prepare for lazy initialization, you create an instance of Lazy<T>.
If you delve into the source code, you'll see that Lazy<T>
ultimately uses Activator
:
return new Lazy<T>.Boxed((T)Activator.CreateInstance(typeof(T)));
This is just a shortcut for using reflection. Since it's not instantiating the type via the actual generic type argument (new T()
) but rather invoking the constructor through reflection, no where T : new()
constraint is needed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With