Как Lazy <T>обходит необходимость в ограничении new ()? - PullRequest
14 голосов
/ 15 ноября 2011

Пример 1 (не компилируется):

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"); }
}

Результат:

Невозможно создать экземпляр типа переменной 'T', поскольку у него нет ограничения new ()

Пример 2 (работы):

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"); }
}

Результат:

i was created

1 Ответ

17 голосов
/ 15 ноября 2011

Если вы углубитесь в исходный код, вы увидите, что Lazy<T> в конечном итоге использует Activator:

return new Lazy<T>.Boxed((T)Activator.CreateInstance(typeof(T)));

Это просто ярлык для использования отражения. Поскольку это не создание экземпляра типа через фактический аргумент универсального типа (new T()), а скорее вызов конструктора посредством отражения, ограничение where T : new() не требуется.

...