Как я уже говорил в комментариях к другому ответу, необходимость в параметре ref является запахом кода. Прежде всего, если вы делаете это в методе, вы нарушаете принцип единой ответственности, но, что более важно, код можно повторно использовать только в пределах вашей иерархии наследования.
Здесь можно вывести шаблон:
public class LazyInit<T>
where T : class
{
private readonly Func<T> _creationMethod;
private readonly object syncRoot;
private T _instance;
[DebuggerHidden]
private LazyInit()
{
syncRoot = new object();
}
[DebuggerHidden]
public LazyInit(Func<T> creationMethod)
: this()
{
_creationMethod = creationMethod;
}
public T Instance
{
[DebuggerHidden]
get
{
lock (syncRoot)
{
if (_instance == null)
_instance = _creationMethod();
return _instance;
}
}
}
public static LazyInit<T> Create<U>() where U : class, T, new()
{
return new LazyInit<T>(() => new U());
}
[DebuggerHidden]
public static implicit operator LazyInit<T>(Func<T> function)
{
return new LazyInit<T>(function);
}
}
Это позволяет вам сделать это:
public class Foo
{
private readonly LazyInit<Bar> _bar1 = LazyInit<Bar>.Create<Bar>();
private readonly LazyInit<Bar> _bar2 = new LazyInit<Bar>(() => new Bar("foo"));
public Bar Bar1
{
get { return _bar1.Instance; }
}
public Bar Bar2
{
get { return _bar2.Instance; }
}
}